home *** CD-ROM | disk | FTP | other *** search
- ;---------------------------------------------------------------------------
- ; PCMCIA ethernet card driver for A600/A1200
- ;---------------------------------------------------------------------------
- ;
- ; HISTORY:
- ;
- ; 10-4-97 v0.1 - Created by Bruce Abbott (bhabbott@inhb.co.nz)
- ; *** First Aminet Release ***
- ;
- ; 29-4-97 v0.2 - Implemented CMD_ONLINE/OFFLINE/FLUSH (for Miami).
- ;
- ; - Enabled interrupts during RemoteWrite (no more serial
- ; port overruns!).
- ;
- ; 6-5-97 v0.3 - Added a flag so that we won't try to ReleaseCard()
- ; unless there was a successful OwnCard()!
- ;
- ; 17-5-97 v0.4 - CMD_CONFIGINTERFACE now overrides the default hardware
- ; address (for Miami).
- ;
- ; - Device now goes offline if the PCMCIA card is removed.
- ;
- ; - CMD_ONEVENT implemented.
- ;
- ; - Loosened hardware address verification to accept the
- ; Accton EN2216.
- ;
- ; - Unrolled loops to improve data transfer speed. Now
- ; about 20% faster on an unexpanded A600.
- ;
- ; - Hack to fix problem with missed interrupts. Now we
- ; clear the Gayle interrupt bits instead of letting
- ; card.resource do it for us.
- ;
- ; *** Second Aminet Release ***
- ;
- ; 29-7-97 v0.5 - Accepts 802.3 packets (untested).
- ;
- ; - Sets BROADCAST bit in io_flags when appropriate.
- ;
- ; - Now examines PCMCIA attribute memory to determine
- ; value to write into Card Configuration Register.
- ;
- ; - If attribute memory not found, tries to open the file
- ; "s:cnetdev.config" to get Card Configuration Register
- ; offset, Configuration ID, and ROM Station Address.
- ;
- ; *** Third Aminet Release ***
- ;
- ;22-12-97 v0.6 - I/O addressing now supports 64KByte range (was 1KB).
- ;
- ; - Tighter data transfer loops, slightly faster on '030.
- ;
- ; - Accepts all Card Configuration Register address sizes.
- ;
- ; - Removed cnet.config stuff (replaced with hardware mod).
- ;
- ; - Now cards are hot-swappable.
- ;
- ; - Un-supported commands now return S2ERR_NOT_SUPPORTED.
- ;
- ; *** 4th Aminet Release ***
- ;
- ;21-4-98 v0.7 - fixed harmless bug in init_nic - remote DMA timeout test
- ; could not fail!
- ;
- ; - Now remembers copytobuf/copyfrombuf tags for each opener.
- ; Allows simultaneous use of eg. AmiTCP and Envoy.
- ;
- ; - OnEvent types ONLINE and OFFLINE now return immediately
- ; if the device is already in the wanted state.
- ;
- ; *** 5th Aminet Release ***
- ;
- ;17-12-98 v0.8 - fixed bug in OnEvent: was using wrong register to test
- ; ONLINE flag.
- ;
- ; 1-6-99 v0.9 - Added support for multicasting, statistics, orphan packets,
- ; exclusive and promiscuous modes.
- ;
- ; *** 6th Aminet Release ***
- ;
- ; 5-7-99 v1.0 - Fixed bug in readpacket: MCAST flag was also set when packet
- ; was BCAST.
- ;
- ; *** 7th Aminet Release ***
- ;
- ; 7-7-99 v1.1 - Fixed bug: delmulticast always failed due to bad testing
- ; for multicast address match.
- ;
- ; - Fixed bug: readpacket was getting incorrect src and dst
- ; addresses (A4 was pointing to prhdr instead of etherhdr).
- ;
- ; - Included put_multi in init_nic (need to reload multicast
- ; bits if card is removed and re-inserted)
- ;
- ; - Added 4 to rx ios2_datalength in raw mode. Shapeshifter
- ; seems to need this (why?)
- ;
- ; *** 8th Aminet release ***
- ;
- ;7-5-00 v1.2b1 - Since there has been almost ten months without an update,
- ; I, Harry Sintonen <sintonen@iki.fi>, decided to have a go.
- ;
- ; - Reformatted this source code: Now registers are always in
- ; lowercase, for better readability.
- ;
- ; - Added MN_LENGTH check for OpenDevice() (S2R3 and NSD require
- ; this).
- ;
- ; - Fixed a bug: If TAG_IGNORE, TAG_MORE or TAG_SKIP were used
- ; in the IOSana2Req's taglist Open_Unit got really confused,
- ; throwing enforcer hits, and in a worst case, crashing the
- ; machine. Now uses utility.library GetTagData().
- ;
- ; - Optimized dbf loops to subq + branch for better 020+
- ; performance. Made several other miscallenous optimizations
- ; thruout the code.
- ;
- ; - More bugs fixed: DoEvent examined dd_eventlist before
- ; Disable(). devcmd_addmulticast and devcmd_delmulticast
- ; didn't lock the list, devcmd_delmulticast called Enable()
- ; without Disable() when no multicast was found. Protected
- ; dd_multicasts list with semaphore. dd_bufmanlist was
- ; accessed without list arbitration, added Disable()/Enable()
- ; pair when needed.
- ;
- ; - Added support for S2_PacketFilter tag. Speedup: replaced
- ; several list related calls with macros.
- ;
- ; - Rewrote CMD_READ handling: Added proper Multiple Protocol
- ; Stack Support, it was really broken before. Basically this
- ; means that each opener gets all the packets necessary. If a
- ; packet comes in that fills a request for more than one
- ; opener of the device, *all* of them will get a copy of the
- ; packet. Of course each caller can ask RAW or non-RAW version
- ; of the packet. cnet.device fully comply to S2R2 now!
- ;
- ; - Since complies to S2R2, added NewStyleDevice (NSD) support.
- ; Also added S2R3 S2_DMACopyFromBuff32 tag support, however
- ; this feature is currently disabled. ***
- ; S2_DMACopyToBuff32 would only pay off if: 1) there is only
- ; one caller for this packet, and 2) there is no packet filter
- ; for this caller.
- ;
- ; - More speedups: Replaced exec Disable() and Enable() calls
- ; with macros. Yet more list related calls replaced with
- ; macros.
- ;
- ; - Yet more bugs fixed: CMD_FLUSH didn't abort S2_READORPHANs.
- ; CMD_OFFLINE didn't abort pending CMD_READs, S2_READORPHANs
- ; and CMD_WRITEs. CMD_READ and S2_READORPHAN didn't check for
- ; card being online. S2_ONEVENT didn't check if it knows the
- ; event condition(s) specified, instead requests for unknown
- ; event(s) would never have got returned. Also S2_ONEVENT
- ; returned the ioreq even if it was queued. S2_CONFIGINTERFACE
- ; worked more than once, it *must* only work once.
- ; OpenDevice() incorrectly required S2_CopyFromBuff and
- ; S2_CopyToBuff tags to be present.
- ;
- ; - Yet more speedups: DoEvent uses global cached device
- ; pointer.
- ;
- ; - init_card and init_nic fire S2EVENT_ERROR|S2EVENT_HARDWARE
- ; event if something goes wrong. Trying to send too big of a
- ; packet trigger S2EVENT_TX. If packet gets dropped during
- ; receive S2EVENT_ERROR|S2EVENT_RX event is triggered. If
- ; copyfrombuf while transmitting fails S2EVENT_TX|S2EVENT_BUFF
- ; event is triggered, and similarily if copytobuf while
- ; receiving fails S2EVENT_RX|S2EVENT_BUFF event is triggered.
- ;
- ; - Extensively debugged for 18+6 hours to make 1st early beta
- ; possible...
- ;
- ; - Currently at least following should work: CMD_READ,
- ; CMD_WRITE, CMD_FLUSH, S2_DEVICEQUERY, S2_GETSTATIONADDRESS,
- ; S2_CONFIGINTERFACE, S2_ADDMULTICASTADDRESS,
- ; S2_DELMULTICASTADDRESS, S2_MULTICAST, S2_BROADCAST,
- ; S2_TRACKTYPE, S2_UNTRACKTYPE, S2_GETTYPESTATS,
- ; S2_GETSPECIALSTATS, S2_GETGLOBALSTATS, S2_ONEVENT,
- ; S2_READORPHAN, S2_ONLINE, S2_OFFLINE and NSCMD_DEVICEQUERY.
- ;
- ; - Tested with sanamon, sanautil, miamidx and genesis.
- ;
- ; *** internal 1.2beta1 release ***
- ;
- ;9-5-00 v1.2b2 - initRoutine trashed a6 by leaving execbase in it, but since
- ; it *is* execbase originally it was harmless. Silly. :)
- ;
- ; - Misc minor changes here and there.
- ;
- ; - Added device expunge. esp. cool for debugging, no more those
- ; damn annoying reboots. Also someone might want to quit
- ; protocol stack, avail flush, and use some other card without
- ; the need to reboot. Now DDF_CONFIGURED is reset only on
- ; device flush, this means that pulling the card out doesn't
- ; cut the connection anymore, and you can continue by plugging
- ; the card back in. v1.2b1 didn't allow this hot swapping
- ; trick, but v1.1 did.
- ;
- ; - Bugfixes: initRoutine crashed if utility.library v36 failed
- ; to open. Partially successful OpenDevice ate some resources,
- ; now it should be able to back out in all cases. S2_OFFLINE
- ; should, I quote: "Aborts all pending reads and writes with
- ; ios2_Error set to S2ERR_OUTOFSERVICE.". However this makes
- ; MiamiDx die a horrible death. Took me 10 hours to find why.
- ; Damn it! Disabled IO aborting and now it works. D'oh!
- ;
- ; - Speedup: Implemented turbo RemoteRead & RemoteWrite loops,
- ; they use longword access to 16bit register. Don't worry,
- ; this works, but honestly I have no clue why. Enabled DMA for
- ; both regular and raw CMD_WRITEs. At least MiamiDx support
- ; S2_DMACopyFromBuff32. Moving 30mb mpg between my amiga and
- ; laptop result about 450kb/s upload and 500kb/s download
- ; speed. v1.1 and the same environment gave about 420kb/s
- ; upload and 450kb/s download speed.
- ; (ftp client AmFTP 1.92, ftpd Version 6.2/OpenBSD/Linux-0.10)
- ;
- ; - Made Makefile generate 68000 version of the device. No real
- ; differences yet tho. this version is untested!
- ;
- ; *** internal 1.2beta2 release ***
- ;
- ;16-5-00 v1.2b3 Got a report that v1.2b2 is actually slower than v1.2b1.
- ; Well I wrote a simple AmigaE program that I can use to
- ; benchmark cnet.device CMD_WRITE. Turned out that turboio
- ; transfer ~679kb/s and non-turboio 697kb/s without DMA
- ; transfer, in DMA mode the same figures are 694kb/s vs. 713
- ; kb/s. Oh dear, this is it, I disabled turboio. :) Thanks go
- ; to Tundrah for the tip. BTW: it seems we're finally getting
- ; there, he get ~770kb/s real life transfer speed using FTP
- ; (Apollo ethernet, 060 @ 66). Not bad. Btw benchmarking
- ; CMD_READ is a bit problematic for me as I don't have really
- ; state of the art machine on the other end and it can't feed
- ; the card at the full speed. However Tundrah also told me
- ; that for some reason MiamiDx is slow compared to Genesis. I
- ; did some tests with both MiamiDx and Genesis, used ftp
- ; client AmFTP 1.92 and ftpd Version 6.2/OpenBSD/Linux-0.10.
- ; Download speed with Genesis was 720kb/s and with MiamiDx 530
- ; kb/s. Genesis is %33 faster. For fucks sake wtf Miami is
- ; doing? busyloops or what? :) This probably means that
- ; someone should make a MNI driver. Any volunteers?
- ;
- ; - Forget that mumbo jumbo about MMU speedup hack that was
- ; mentioned in v1.2b2. 1) no real speedup due the way I/O
- ; is accessed. 2) many amiga 060 turbo cards don't have
- ; special hardware to handle writebuffer burst write ->
- ; undefined behavior. (Thanks to Ralph Schmidt for helping me
- ; understand this)
- ;
- ; - Bugfix: AbortIO failed to abort S2_MULTICAST or S2_BROADCAST
- ; requests.
- ;
- ; *** internal 1.2beta3 release ***
- ;
- ;19-5-00 v1.2b4 Misc little changes here and there, nothing major.
- ;
- ; - Speedup: inlined optimized version of RemoteRead for reading
- ; prhdr and etherheader. Joined rx_header and rxbuffer. As a
- ; result code simplified and sped up. For me the speedup is
- ; +2kb/s. Inlined couple of other subroutines that are called
- ; only once.
- ;
- ; - Speedup: Got a report from darza saying that turboio indeed
- ; is faster with `cnet' card. He got 720kb/s with v1.1,
- ; v1.2beta1 and v1.2beta3, but 750kb/s with v1.2beta2. Eek! :)
- ; Tweaked makefile to compile separate turboio version. It is
- ; up to user to find out which one is faster. Currently non-
- ; turboio ftp download peaked 754kb/s. Turboio version peaked
- ; 771kb/s. Could be that turboio is faster on 060 @ 50 systems
- ; and non-turboio on overclocked 060 systems. Why? Maybe some
- ; I/O timing issues... No idea really, just guessing. Need to
- ; ask Tundrah to do more benchmarking. :)
- ;
- ; - Improvements: added support for S2_ADDMULTICASTADDRESSES and
- ; S2_DELMULTICASTADDRESSES (Multicast address range extensions
- ; to SANA-II Rev 3). Implemented S2_ADDMULTICASTADDRESS and
- ; S2_DELMULTICASTADDRESS using range of addr -> addr. Added
- ; CPU type to version string. Added 68020 CPU check to 68020+
- ; version. Device IDString no longer has '$VER: ' included.
- ; Now uses CARDF_POSTSTATUS instead of a hack if card.resource
- ; V39+ is available (note that KS 3.0 has *V37* card.resource,
- ; and KS 3.1 has V40). Added workaround for Genesis bug, it
- ; calls S2_ONLINE before S2_CONFIGINTERFACE.
- ;
- ; *** internal 1.2beta4 release ***
- ;
- ;25-5-00 v1.2 - Made compile with standard os-includes.
- ;
- ; *** 9th Aminet release ***
- ;
-
-
- ; todo: Do some more 020+ optimizations (the ones that really pay off!)
- ; Make it use memory pool (not really worth it I think)
- ; CopyTo/CopyFrom 16/32 support? (ADCD_2.1:DevInfo/Networking/SANA2Revision3)
- ; Add support for more cards? (not in this device in this life, unless easily implemented)
- ;
-
-
- ; configured from makefile
- ;debug = 1
- ;verbose=1
- ;turboio = 1
-
-
- ; misc flags
- ;realdisable=1 ; use exec functions or macros ?
-
-
- include exec/types.i
- include exec/nodes.i
- include exec/lists.i
- include exec/libraries.i
- include exec/errors.i
- include exec/initializers.i
- include exec/resident.i
- include exec/memory.i
- include exec/interrupts.i
- include exec/semaphores.i
- include exec/ports.i
- include exec/io.i
- include exec/devices.i
- include exec/tasks.i
- include devices/timer.i
- IFND realdisable
- include exec/ables.i
- ENDC
-
- include funcdef.i
- include exec/exec_lib.i
-
- IFND _LVOGetSysTime
- _LVOGetSysTime = -66 ; timer lib function
- ENDC
- IFND _LVOGetTagData
- _LVOGetTagData = -36 ; utility lib function
- ENDC
-
- include pcmcia.i ; card.resource etc.
- include sanaii.i ; the essential network stuff
- include cnet.i ; hardware specific stuff
-
-
- VERSION = 1
- REVISION = 2
-
- VERSTR macro
- dc.b "1.2 (25.5.2000)"
- endm
-
-
- ; 1uS delay before nic register access
- ; May not be required with slower CPUs.
-
- delay MACRO
- ; tst.b $bfe001 ; at least 1uS, even on fast machines
- ENDM
-
-
- MYDISABLE MACRO
- IFD realdisable
- jsr _LVODisable(a6)
- ELSE
- MOVE.W #$4000,$DFF09A
- ADDQ.B #1,IDNestCnt(A6)
- ENDC
- ENDM
-
- MYENABLE MACRO
- IFD realdisable
- jsr _LVOEnable(a6)
- ELSE
- SUBQ.B #1,IDNestCnt(A6)
- BGE.S .MYENABLE\@
- MOVE.W #$C000,$DFF09A
- .MYENABLE\@:
- ENDC
- ENDM
-
- MYREMHEAD MACRO
- MOVE.L (A0),A1
- MOVE.L (A1),D0
- BEQ.S .MYREMHEAD\@
- MOVE.L D0,(A0)
- EXG.L D0,A1
- MOVE.L A0,LN_PRED(A1)
- .MYREMHEAD\@
- ENDM
-
- ;===========================================================================
-
-
- section 0,CODE
-
-
- ;-----------------------------------------------------------------------
- ; The first executable location. This should return an error
- ; in case someone tried to run you as a program (instead of
- ; loading you as a device).
-
- start_exe:
- moveq #-1,d0 ; it's a device, not an application!
- rts
-
-
- ;-----------------------------------------------------------------------
- ; A romtag structure. After your driver is brought in from disk, the
- ; disk image will be scanned for this structure to discover magic constants
- ; about you (such as where to start running you from...).
- ;-----------------------------------------------------------------------
-
- romtag:
- dc.w RTC_MATCHWORD ; RT_MATCHWORD
- dc.l romtag ; RT_MATCHTAG
- dc.l Endcode ; RT_ENDSKIP
- dc.b RTF_AUTOINIT ; RT_FLAGS
- dc.b VERSION ; RT_VERSION
- dc.b NT_DEVICE ; RT_TYPE
- dc.b 0 ; RT_PRI
- dc.l DeviceName ; RT_NAME
- dc.l IDString ; RT_IDSTRING
- dc.l Init ; RT_INIT
-
- Init:
- dc.l dd_extsize ; data space size
- dc.l funcTable ; pointer to function initializers
- dc.l dataTable ; pointer to data initializers
- dc.l initRoutine ; routine to run at startup
-
- funcTable:
- dc.w -1
- dc.w Open_Device-funcTable
- dc.w Close_Device-funcTable
- dc.w Expunge_Device-funcTable
- dc.w _Null-funcTable
- dc.w _DevBeginIO-funcTable
- dc.w _DevAbortIO-funcTable
- dc.w -1
-
- dataTable:
- INITBYTE LN_TYPE,NT_DEVICE
- INITLONG LN_NAME,DeviceName
- INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
- INITWORD LIB_VERSION,VERSION
- INITWORD LIB_REVISION,REVISION
- INITLONG LIB_IDSTRING,idString
- dc.w 0
-
-
- include debugs.i
-
-
-
- ;=======================================================
- ; initRoutine
- ;=======================================================
- ;
- ; This routine gets called after the device has been allocated.
- ; The device pointer is in d0. The AmigaDOS segment list is in a0.
- ; If it returns the device pointer, then the device will be linked
- ; into the device list. If it returns NULL, then the device will
- ; be unloaded. This call is single-threaded.
- ;
- ; input: a0 = seglist
- ; d0 = device
- ; a6 = execbase
- ;
- initRoutine:
- movem.l d1-d7/a0-a5,-(sp)
- move.l d0,a5
- move.l a0,a4
-
- ifge __CPU-68020
- btst #AFB_68020,AttnFlags+1(a6)
- beq.s .err
- endc
-
- lea utilityName(pc),a1
- moveq #36,d0
- jsr _LVOOpenLibrary(a6)
- move.l d0,utility_base ; store utilitybase
- beq.s .err ; oops failed, return failure
-
- move.l a4,dd_SegList(a5) ; seglist for expunge
- move.l a6,exec_base ; local copy of execbase
- move.l a5,me_myself ; for speedup
-
- move.l a5,d0
- .pop:
- movem.l (sp)+,d1-d7/a0-a5
- rts
-
- .err:
- moveq #0,d0
- bra.s .pop
-
-
- _Null:
- moveq #0,d0
- rts
-
-
-
-
- ;----------------------------------------------------------------------
- ;
- ; Here begins the system interface commands. When the user calls
- ; OpenDevice/CloseDevice/RemDevice, this eventually gets translated
- ; into a call to the following routines (Open_Device/Close_Device/
- ; Expunge_Device). Exec has already put our device pointer in a6 for
- ; us.
-
-
-
- ;=================================================================
- ; Open Device
- ;=================================================================
- ;
- ; error = Open_Device(device, ioreq, unitnum, flags)
- ; d0 a6 a1 d0 d1
- ;
- ; Open sets the IO_ERROR field on an error. If it was successfull,
- ; we should also set up the IO_UNIT and LN_TYPE fields. Exec takes
- ; care of setting up IO_DEVICE.
- ;
- Open_Device:
- ;
- ;** Subtle point: any AllocMem() call can cause a call to this device's
- ;** expunge vector. If LIB_OPENCNT is zero, the device might get expunged.
- ;
- addq.w #1,lib_opencnt(a6) ; Fake an opener for duration of call <|>
-
- bug <10,"cnet: OpenDevice(ioreq $%lx, unit %ld, flags $%02lx)",10>,a1,d0,d1
-
- ifgt 0
- ifd debug
- ifd verbose
- move.l #100000,d0
- .wait:
- tst.b $bfe001
- subq.l #1,d0
- bne.s .wait
- endc
- endc
- endc
-
- movem.l d2-d4/a2-a4/a6,-(sp)
- move.l a6,a3 ; a3 = device
- move.l a1,a4 ; a4 = ioreq
- move.l d0,d4 ; d4 = unit
-
- cmp.w #IOS2_SIZE,mn_length(a4) ; reject invalid requests
- blt .badcaller
-
- btst #DDB_MINE,dd_flags2(a3)
- bne .isexclusive
-
- btst #SANA2OPB_MINE,d1 ; want exclusive mode ?
- beq.s .init
-
- cmp.w #1,lib_opencnt(a3) ; must not be any other openers
- bne .isnonexcl
- bset #DDB_MINE,dd_flags2(a3) ; set exclusive mode
- btst #SANA2OPB_PROM,d1
- beq.s .init
- bset #DDB_PROM,dd_flags2(a3) ; set promiscuous mode
- .init:
-
-
- move.l a3,a1
- bsr init_device ; init device data structures
-
- move.l a3,a0
- move.l a4,a1
- move.l d4,d0
- bsr Open_Unit ; open unit
- move.l d0,io_unit(a4)
- beq .openerr
-
-
- btst #DDB_NICUP,dd_flags(a3) ; nic already initialised ?
- bne.s .nickdone
- move.l a3,a1
- bsr init_card ; init PCMCIA card
- tst.l d0
- bne.s .error
- move.l a3,a1
- bsr init_nic ; set up nic
- tst.l d0
- bne.s .error
- .nickdone:
-
-
-
- btst #DDB_OFFLINE,dd_flags(a3) ; previously put offline ?
- bne.s .opened
- bset #DDB_ONLINE,dd_flags(a3) ; ready to accept packets
- .opened:
-
-
- clr.b io_error(a4) ; IMPORTANT: Mark IORequest as "complete"
- move.b #NT_REPLYMSG,ln_type(a4)
- addq.w #1,lib_OpenCnt(a3) ; opened successfully
- bclr #LIBB_DELEXP,lib_flags(a3) ; prevent delayed expunges
-
- moveq #0,d0
- bug <"cnet: OpenDevice OK",10,10>
-
-
- .done:
- movem.l (sp)+,d2-d4/a2-a4/a6
- subq.w #1,lib_opencnt(a6) ; ** End of expunge protection <|>
- rts
-
-
-
- .badcaller
- bug <"cnet: OpenDevice invalid MN_LENGTH!",10>
- bra.s .openerr
-
- .isexclusive:
- bug <"cnet: device already in use exclusively!",10>
- bra.s .openerr
-
- .isnonexcl:
- bug <"cnet: device already in use non-exclusively!",10>
- bra.s .openerr
-
- .notask:
- ; task creation failed, cleanup; kill the nic!
- move.l a3,a1
- bsr kill_nic
-
- .error:
- move.l dd_cardres(a3),d0 ; did card.resource open ?
- beq.s .nocard
- move.l d0,a6
- bclr #DDB_OWNED,dd_flags(a3) ; did we own card ?
- beq.s .nocard
- lea dd_cardhandle(a3),a1
- moveq #CARDF_REMOVEHANDLE,d0
- jsr _LVOReleaseCard(a6) ; release card
- .nocard:
-
-
- move.l ios2_buffermanagement(a4),d0
- beq.s .nobufman ; got a buffermanagement pointer ?
- clr.l ios2_buffermanagement(a4)
-
- move.l exec_base(pc),a6
-
- move.l d0,a1
- move.l d0,a2
- bug <"cnet: OpenDevice remove bufman at $%lx",10>,a1
- MYDISABLE ; lock access to list
- REMOVE ; remove bufman struct from list
- MYENABLE ; release lock on list
- move.l a2,a1
- moveq #bufman_sizeof,d0
- jsr _LVOFreeMem(a6) ; discard buffer management struct
- .nobufman:
-
-
- .openerr:
- moveq #IOERR_OPENFAIL,d0 ; error, opendevice failed!
- move.b d0,io_error(a4)
- move.l d0,io_unit(a4)
- move.l d0,io_device(a4) ; IMPORTANT: trash IO_DEVICE on open failure
- bug <"cnet: OpenDevice failed!",10,10>
- bra.s .done
-
-
-
- ;===============================================================
- ; unit=Open Unit(device, ioreq, unitnum)
- ; d0 a0 a1 d0
- ;===============================================================
- ;
- ; Get the caller's buffer copy callback vectors
- ;
- Open_Unit:
- bug <"cnet: Open_Unit(ioreq $%08lx) taglist: $%08lx",10>,a1,ios2_buffermanagement(a1)
-
- movem.l d2-d6/a2-a5,-(sp)
- move.l a0,a4 ; a4 = device
- move.l a1,a5 ; a5 = ioreq
- tst.l d0 ; only unit 0 is supported
- bne .error
-
- ; If null taglist is supplied we don't fail!
-
- move.l ios2_buffermanagement(a5),d0 ; tag list supplied?
- beq .ok
- moveq #0,d2 ; d2 = tags found
- move.l d0,a2 ; a2 = tag list
-
- ; Note: I don't complain if I can't find pointers to the callback
- ; routines. This is because there are some programs that may need to
- ; open the device, but will never use any device commands that
- ; require the callbacks. Instead I check on CMD_READ, CMD_READORPHAN
- ; and CMD_WRITE for missing routines.
-
- move.l exec_base(pc),a6
-
- moveq #bufman_sizeof,d0 ; allocate memory for bufman vectors
- moveq #MEMF_PUBLIC,d1
- jsr _LVOAllocMem(a6)
- move.l d0,ios2_buffermanagement(a5) ; return bufman node
- beq .error
-
- move.l d0,a3
-
- move.l utility_base(pc),a6
-
- ; get copyfrom functions:
-
- move.l #S2_COPYFROMBUFF,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- move.l d0,bufman_copyfrombuf(a3)
-
- ; This is new SANA-II V3 Addition
-
- move.l #S2_DMACopyFromBuff32,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- move.l d0,bufman_dmacopyfrombuf32(a3)
-
- bug <"cnet: S2_DMACopyFromBuff32 = $%08lx",10>,d0
-
- ; get copyto functions:
-
- move.l #S2_COPYTOBUFF,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- move.l d0,bufman_copytobuf(a3)
-
- ; This is new for SANA-II V3 Addition
-
- move.l #S2_DMACopyToBuff32,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- move.l d0,bufman_dmacopytobuf32(a3)
-
- bug <"cnet: S2_DMACopyToBuff32 = $%08lx",10>,d0
-
- ; And this is new SANA-II V2 Addition
- move.l #S2_PACKETFILTER,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- move.l d0,bufman_packetfilter(a3) ; if null everything get thru
-
- ifd debug
- bug <"cnet: S2_PacketFilter = $%08lx",10>,d0
- ifd verbose
- tst.l d0
- beq.s .v1
- move.l d0,a0
- bug <"cnet: PacketFilter h_Entry = $%08lx h_SubEntry = $%08lx h_Data = $%08lx",10>,8(a0),12(a0),16(a0)
- .v1:
-
- move.l #S2_COPYFROMBUFF16,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- bug <"cnet: S2_CopyFromBuff16 = $%08lx",10>,d0
-
- move.l #S2_COPYTOBUFF16,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- bug <"cnet: S2_CopyToBuff16 = $%08lx",10>,d0
-
- move.l #S2_COPYFROMBUFF32,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- bug <"cnet: S2_CopyFromBuff32 = $%08lx",10>,d0
-
- move.l #S2_COPYTOBUFF32,d0
- moveq #0,d1
- move.l a2,a0
- jsr _LVOGetTagData(a6)
- bug <"cnet: S2_CopyToBuff32 = $%08lx",10>,d0
-
- endc
- endc
-
- move.l exec_base(pc),a6
-
- ; Init the list for CMD_READ requests
- lea bufman_rxqueue(a3),a0
- NEWLIST a0
-
- bug <"cnet: addbufman at $%lx",10>,a3
- lea dd_bufmanlist(a4),a0
- move.l a3,a1
- MYDISABLE ; lock access to list
- ADDHEAD ; add to buffer management list
- MYENABLE ; release lock on list
- bra.s .ok
-
- .error:
- moveq #0,d0 ; return error
- bra.s .done
-
- .ok:
- moveq #1,d0 ; return OK
- .done:
- movem.l (sp)+,d2-d6/a2-a5
- rts
-
-
-
- ;============================================================
- ; Close Device
- ;============================================================
- ;
- ; Seglist = CloseDevice(ioreq, device)
- ; d0 a1 a6
- ;
- ;
- ; There are two different things that might be returned from the Close
- ; routine. If the device wishes to be unloaded, then Close must return
- ; the segment list (as given to Init). Otherwise close MUST return NULL.
- ;
- ;
- Close_Device:
- bug <10,"cnet: CloseDevice(ioreq $%08lx)",10>,a1
-
- ifgt 0
- ifd debug
- ifd verbose
- move.l #100000,d0
- .wait:
- tst.b $bfe001
- subq.l #1,d0
- bne.s .wait
- endc
- endc
- endc
-
- movem.l a2-a4/a6,-(sp)
- move.l a1,a3 ; a3 = ioreq
- move.l a6,a4 ; a4 = device
-
- moveq #0,d0 ; default: no unload
- tst.w lib_OpenCnt(a4)
- beq .done ; invalid state!
-
- move.l exec_base(pc),a6
-
- moveq #-1,d0
- move.l d0,io_unit(a3) ; We're closed...
- move.l d0,io_device(a3) ; customers not welcome at this IORequest!!
-
- move.l ios2_buffermanagement(a3),d0
- beq.s .nobufman ; got a buffermanagement pointer ?
- clr.l ios2_buffermanagement(a3)
-
- move.l d0,a1
- move.l d0,a2
- bug <"cnet: remove bufman at $%lx",10>,a1
-
- MYDISABLE ; lock access to list
- REMOVE ; remove bufman struct from list
- MYENABLE ; release lock on list
-
- move.l a2,a1
- moveq #bufman_sizeof,d0
- jsr _LVOFreeMem(a6) ; discard buffer management struct
- .nobufman:
-
-
- moveq #0,d0 ; default: no unload
- subq.w #1,lib_OpenCnt(a4) ; one less opener
- bne.s .done ; still open ?
-
- bug <"cnet: devclosedown",10>
-
- ; close down the devive
- move.l a4,a1
- ; a6 = execbase
- bsr devclosedown
-
- moveq #0,d0 ; default: no unload
- btst #LIBB_DELEXP,lib_flags(a4)
- beq.s .done ; delayed expunge pending ?
-
- ; do the expunge
- bug <"cnet: LIBF_DELEXP calling Expunge!",10>
- move.l a4,a6
- bsr.s Expunge_Device
-
- .done:
- movem.l (sp)+,a2-a4/a6
- bug <"cnet: CloseDevice return: $%08lx",10,10>,d0
- rts ; MUST return either zero or the SegList!!!
-
-
-
- ;============================================================
- ; Expunge Device
- ;============================================================
- ;
- ; Seglist = ExpungeDevice(device)
- ; d0 a6
- ;
- ; Expunge is called by the memory allocator when the system is low on
- ; memory (or by us from the CloseDevice above!).
- ;
- ; There are two different things that might be returned from the Expunge
- ; routine. If the device is no longer open then Expunge may return the
- ; segment list (as given to Init). Otherwise Expunge may set the delayed
- ; expunge flag and return NULL.
- ;
- ; One other important note: because Expunge is called from the memory
- ; allocator, it may NEVER Wait() or otherwise take long time to complete.
- ;
- ;
- Expunge_Device:
- bug <10,"cnet: Expunge_Device $%08lx",10>,a6
-
- ifgt 0
- ifd debug
- ifd verbose
- move.l #100000,d0
- .wait:
- tst.b $bfe001
- subq.l #1,d0
- bne.s .wait
- endc
- endc
- endc
-
- tst.w lib_opencnt(a6)
- beq.s .unload ; anyone has us open ?
-
- ; it is still open. set the delayed expunge flag
-
- bug <"cnet: Could not expunge, LIBF_DELEXP set!",10>
- bset #LIBB_DELEXP,lib_flags(a6)
- moveq #0,d0 ; do not unload the seg
- rts
-
-
- .unload
- bug <"cnet: Unloading...",10>
-
- movem.l a4/a6,-(sp)
- move.l dd_SegList(a6),-(sp) ; seglist to return in d0
-
- move.l a6,a4
- move.l exec_base(pc),a6
-
- ; put the hardware offline
- move.l a4,a1
- ; a6=execbase
- bug <"cnet: devclosedown",10>
- bsr devclosedown
-
-
- ; get rid of the timer.device stuff we might have allocated:
- lea timereq(pc),a1
- move.l io_device(a1),d0
- beq.s .notimerdev ; was timer ever opened?
- addq.l #1,d0
- beq.s .notimerdev ; error can be also indicated by -1!
- bug <"cnet: closedevice timer ior $%08lx",10>,a1
- jsr _LVOCloseDevice(a6) ; close it
- .notimerdev
-
-
- ; release the card, if we own it. note that there is
- ; no CloseResource() call.
- move.l dd_cardres(a4),d0 ; did we open card.resource at some point ?
- beq.s .nocard
- bclr #DDB_OWNED,dd_flags(a4) ; do we own card ?
- beq.s .nocard
- move.l a6,-(sp)
- move.l d0,a6
- lea dd_cardhandle(a4),a1
- moveq #CARDF_REMOVEHANDLE,d0
- bug <"cnet: releasing cardhandle $%08lx",10>,a1
- jsr _LVOReleaseCard(a6) ; release card
- move.l (sp)+,a6
- .nocard:
-
-
- ; close utilitybase
- move.l utility_base(pc),a1
- bug <"cnet: closing utilitybase $%08lx",10>,a1
- jsr _LVOCloseLibrary(a6)
-
-
- ; unlink from device list
- move.l a4,a1
- bug <"cnet: removing device node $%08lx",10>,a1
- REMOVE
-
-
- ; free our memory (must calculate from LIB_POSSIZE & LIB_NEGSIZE)
- moveq #0,d0
- move.l a4,a1 ; devicebase
- move.w lib_negsize(a4),d0
- sub.l d0,a1 ; calculate base of functions
- add.w lib_possize(a4),d0 ; calculate size of functions + data area
- jsr _LVOFreeMem(a6)
-
- bug <"cnet: Unload done! cnet.device expunged!",10,10>
-
- movem.l (sp)+,d0/a4/a6 ; pop regs and seglist pointer
- rts
-
-
-
- ;======================================================================
- ; devclosedown(device, execbase)
- ; a1 a6
- ;======================================================================
- ;
- ; Put the nic into sleep... also do whatever nececcary hw magic
- ; before device closedown. mark the device offline and unconfigured.
- ;
- devclosedown:
- ;and.b #~(DDF_ONLINE|DDF_CONFIGURED),dd_flags(a1) ; not online, not configured
- and.b #~DDF_ONLINE,dd_flags(a1) ; not online
- and.b #~(DDF_MINE|DDF_PROM),dd_flags2(a1) ; cancel exclusive mode, cancel promiscuous mode
- bra kill_nic ; stop controller
-
-
-
- ;===============================================================
- ; Dev_BeginIO
- ;===============================================================
- ; the entry point for all device commands
- ;
-
- CNOP 0,4
-
- _DevBeginIO:
- move.w io_command(a1),d0 ; get command number
- move.b #NT_MESSAGE,ln_type(a1) ; make sure type is message
- cmp.w #S2_END,d0
- bhs .berror ; valid command?
- lsl.w #2,d0
- move.l .cmds(pc,d0.w),d0 ; get command vector
- bne.s .ok
- .error:
- move.b #IOERR_NOCMD,io_error(a1)
- bra TermIO ; return invalid command
- .ok:
- move.l d0,a0
- clr.b io_error(a1) ; no errors yet
-
- ifgt 0
- ifd debug
- ifd verbose
- moveq #0,d0
- move.w io_command(a1),d0
- bug <"cnet: BeginIO ioreq $%08lx cmd %ld",10>,a1,d0
- move.l #300000,d0
- .wait:
- tst.b $bfe001
- subq.l #1,d0
- bne.s .wait
- endc
- endc
- endc
-
- jmp (a0) ; jump to command
-
-
- ; command vectors
-
- CNOP 0,4
-
- .cmds:
- dc.l 0 ; 0
- dc.l 0 ; 1
- dc.l devcmd_read ; 2 = cmd_read
- dc.l devcmd_write ; 3 = cmd_write
- dc.l 0 ; 4
- dc.l 0 ; 5
- dc.l 0 ; 6
- dc.l 0 ; 7
- dc.l devcmd_flush ; 8 = cmd_flush
- dc.l devcmd_devicequery ; 9 = S2_DEVICEQUERY
- dc.l devcmd_getstationaddress ; 10= S2_GETSTATIONADDRESS
- dc.l devcmd_configinterface ; 11= S2_CONFIGINTERFACE
- dc.l 0 ; 12
- dc.l 0 ; 13
- dc.l devcmd_addmulticast ; 14= S2_ADDMULTICASTADDRESS
- dc.l devcmd_delmulticast ; 15= S2_DELMULTICASTADDRESS
- dc.l devcmd_multicast ; 16= S2_MULTICAST
- dc.l devcmd_broadcast ; 17= S2_BROADCAST
- dc.l devcmd_tracktype ; 18= S2_TRACKTYPE
- dc.l devcmd_untracktype ; 19= S2_UNTRACKTYPE
- dc.l devcmd_gettypestats ; 20= S2_GETTYPESTATS
- dc.l devcmd_getspecialstats ; 21= S2_GETSPECIALSTATS
- dc.l devcmd_getglobalstats ; 22= S2_GETGLOBALSTATS
- dc.l devcmd_onevent ; 23= S2_ONEVENT
- dc.l devcmd_readorphan ; 24= S2_READORPHAN
- dc.l devcmd_online ; 25= S2_ONLINE
- dc.l devcmd_offline ; 26= S2_OFFLINE
-
- .nsd_supported:
- dc.w 2,3
- dc.w 8,9,10,11
- dc.w 14,15,16,17,18,19,20,21,22,23,24,25,26
- dc.w NSCMD_DEVICEQUERY
- dc.w S2_ADDMULTICASTADDRESSES
- dc.w S2_DELMULTICASTADDRESSES
- dc.w 0
-
- .berror:
- clr.b io_error(a1) ; no error
- cmp.w #S2_ADDMULTICASTADDRESSES,d0
- beq devcmd_addmulticasts
- cmp.w #S2_DELMULTICASTADDRESSES,d0
- beq devcmd_delmulticasts
-
- cmp.w #NSCMD_DEVICEQUERY,d0 ; is it NSCMD_DEVICEQUERY?
- bne .error
-
- ifd verbose
- bug <"cnet: NSCMD_DEVICEQUERY ior $%08lx",10>,a1
- endc
- cmp.l #16,io_length(a1)
- blt .error
- move.l io_data(a1),d0
- beq .error
- move.l d0,a0
- tst.l (a0)+
- bne .error
- tst.l (a0)
- bne .error
-
- ifd verbose
- bug <"cnet: replied with NSDEVTYPE_SANA2!",10>
- endc
- moveq #16,d0
- move.l d0,(a0)+
- move.l #$00070000,(a0)+ ; NSDEVTYPE_SANA2<<16
- move.l #.nsd_supported,(a0)
- move.l d0,io_actual(a1)
- bra TermIO
-
-
-
- ;====================================================================
- ; Abort_IO
- ;====================================================================
- ;
- ; try to cancel a pending ioreq
- ;
- _DevAbortIO:
-
- bug <"cnet: AbortIO ioreq $%08lx",10>,a1
-
- movem.l d2/a2-a4/a6,-(sp)
- move.l a6,a4 ; a4=device
- move.l exec_base(pc),a6
- move.l a1,a2 ; a2=ioreq
-
- moveq #0,d0 ; if already replied silentry ignore
- MYDISABLE ; lock access to lists
- cmp.b #NT_MESSAGE,ln_type(a2) ; only cancel queued ioreq's
- bne.s .done
-
- move.w io_command(a2),d0
- cmp.w #CMD_READ,d0
- beq.s .read
-
- lea dd_orphanlist(a4),a0
- cmp.w #S2_READORPHAN,d0
- beq.s .thisone
-
- lea dd_writelist(a4),a0
- cmp.w #CMD_WRITE,d0
- beq.s .thisone
- cmp.w #S2_MULTICAST,d0
- beq.s .thisone
- cmp.w #S2_BROADCAST,d0
- beq.s .thisone
-
- lea dd_eventlist(a4),a0
- cmp.w #S2_ONEVENT,d0
- beq.s .thisone
-
- bug <"cnet: AbortIO not READ, READORPHAN, WRITE, MULTICAST, BROADCAST or ONEVENT",10>
- moveq #IOERR_NOCMD,d0
- bra.s .done
-
- .read:
- ; Check all nodes in dd_bufmanlist until we succeed to abort:
- ; if we can't find the ioreq in any list, return IOERR_NOCMD.
-
- move.l dd_bufmanlist(a4),a3
- ;bug <"cnet: AbortIO READ bufmanlist 1st: $%08lx",10>,a3
- .readhandle
- moveq #IOERR_NOCMD,d0 ; return failure if we can't find it
- move.l (a3),d2
- beq.s .done ; end of list?
- lea bufman_rxqueue(a3),a0
- ; a2=ioreq
- bsr AbortReq
- tst.l d0
- beq.s .done ; succeeded to abort?
- move.l d2,a3
- bra.s .readhandle
-
- .thisone:
- ; a0=list where the ioreqs should be in
- ; a2=ioreq
- bsr AbortReq
-
- .done:
- MYENABLE ; release lock on lists
-
- movem.l (sp)+,d2/a2-a4/a6
- rts
-
-
-
- ;======================================================================
- ; AbortReq(minlist, ioreq, execbase)
- ; a0 a2 a6
- ;======================================================================
- ;
- ; locate an IO request in a linked list and abort it if found.
- ;
- AbortReq:
- moveq #IOERR_NOCMD,d0
-
- move.l (a0),a0
- .search:
- move.l (a0),d1
- beq.s .done ; end of list ?
- cmp.l a2,a0 ; = ioreq ?
- move.l d1,a0 ; note: movea doesn't change ccs!
- bne.s .search
-
- move.l a2,a1
- ;bug <"cnet: AbortReq aborted $%08lx",10>,a1
- REMOVE ; remove ioreq from list
- move.b #NT_REPLYMSG,ln_type(a2)
- move.b #IOERR_ABORTED,io_error(a2)
- move.l a2,a1
- jsr _LVOReplyMsg(a6) ; reply to originator's message
- moveq #0,d0 ; aborted OK
- .done:
- rts
-
-
-
- ;===========================================================
- ; termio(ioreq)
- ; a1
- ;===========================================================
- ;
- ; return completed ioreq to sender.
- ;
- TermIO:
- move.b #NT_REPLYMSG,ln_type(a1)
- btst #IOB_QUICK,io_flags(a1)
- bne.s .done ; does sender need a reply ?
- move.l a6,-(sp)
- move.l exec_base(pc),a6
- jsr _LVOReplyMsg(a6) ; send reply
- move.l (sp)+,a6
- .done:
- rts
-
-
-
- ;====================================================
- ; CMD_READ
- ;====================================================
- ;
- ; if card is configured and online
- ;
- CNOP 0,4
- devcmd_read:
- ifd verbose
- bug <"cnet: cmd_read(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
- endc
-
- movem.l a2/a3/a6,-(sp)
- move.l a1,a2 ; a2 = ioreq
- move.l io_device(a1),a3 ; a3 = device
-
- btst #DDB_CONFIGURED,dd_flags(a3) ; configured ?
- beq .unconfigured
- btst #DDB_ONLINE,dd_flags(a3) ; online ?
- beq .offline
-
- move.l ios2_buffermanagement(a2),d0
- beq.s .bad ; eeeekh, no bufman ?
- move.l d0,a0
- tst.l bufman_copytobuf(a0)
- beq.s .bad ; this is needed for reading.. :)
-
- bclr #IOB_QUICK,io_flags(a2) ; must be queued
- move.l exec_base(pc),a6
-
- ; add to this ioreq's bufman_rxqueue
-
- lea bufman_rxqueue(a0),a0
- move.l a2,a1
- ifd verbose
- bug <"cnet: CMD_READ ior $%08lx added to bufman_rxqueue $%08lx",10>,a1,a0
- endc
- MYDISABLE
- ADDTAIL ; add ioreq to read queue
- MYENABLE
-
- .done:
- movem.l (sp)+,a2/a3/a6
- rts
-
- .unconfigured:
- moveq #S2WERR_NOT_CONFIGURED,d0 ; error, device is not configured
- move.b #S2ERR_BAD_STATE,io_error(a2)
- bra.s .error
-
- .offline:
- moveq #S2WERR_UNIT_OFFLINE,d0 ; error, device is offline
- move.b #S2ERR_OUTOFSERVICE,io_error(a2)
- bra.s .error
-
- .bad:
- moveq #S2WERR_GENERIC_ERROR,d0 ; error, bad argument
- move.b #S2ERR_BAD_ARGUMENT,io_error(a2)
-
- .error:
- ifd verbose
- bug <"cnet: read ior $%08lx error %ld",10>,a2,d0
- endc
-
- move.l d0,ios2_wireerror(a2)
- move.l a2,a1
- bsr TermIO
- bra.s .done
-
-
-
- ;====================================================
- ; S2_READORPHAN
- ;====================================================
- ;
- ; if card is configured and online
- ;
- CNOP 0,4
- devcmd_readorphan:
- bug <"cnet: readorphan(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
-
- movem.l a2/a3/a6,-(sp)
- move.l a1,a2 ; a2 = ioreq
- move.l io_device(a2),a3
-
- btst #DDB_CONFIGURED,dd_flags(a3) ; configured ?
- beq .unconfigured
- btst #DDB_ONLINE,dd_flags(a3) ; online ?
- beq .offline
-
- move.l ios2_buffermanagement(a2),d0
- beq.s .bad ; eeeekh, no bufman ?
- move.l d0,a0
- tst.l bufman_copytobuf(a0)
- beq.s .bad ; this is needed for reading.. :)
-
- bclr #IOB_QUICK,io_flags(a2) ; must be queued
- move.l exec_base(pc),a6
- lea dd_orphanlist(a3),a0
- move.l a2,a1
- bug <"cnet: S2_READORPHAN ior $%08lx added to orphanlist $%08lx",10>,a1,a0
- MYDISABLE
- ADDTAIL ; add ioreq to orphan queue
- MYENABLE
-
- .done:
- movem.l (sp)+,a2/a3/a6
- rts
-
- .unconfigured:
- moveq #S2WERR_NOT_CONFIGURED,d0 ; error, device is not configured
- move.b #S2ERR_BAD_STATE,io_error(a2)
- bra.s .error
-
- .offline:
- moveq #S2WERR_UNIT_OFFLINE,d0 ; error, device is offline
- move.b #S2ERR_OUTOFSERVICE,io_error(a2)
- bra.s .error
-
- .bad:
- moveq #S2WERR_GENERIC_ERROR,d0 ; error, bad argument
- move.b #S2ERR_BAD_ARGUMENT,io_error(a2)
-
- .error:
- ifd verbose
- bug <"cnet: readorphan ior $%08lx error %ld",10>,a2,d0
- endc
-
- move.l d0,ios2_wireerror(a2)
- move.l a2,a1
- bsr TermIO
- bra.s .done
-
-
-
- ;======================================================
- ; CMD_WRITE
- ;======================================================
- ;
- ; if card is configured and online
- ;
- CNOP 0,4
- devcmd_write:
- ifd verbose
- bug <"cnet: cmd_write(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
- endc
-
- movem.l a2/a3/a6,-(sp)
- move.l a1,a2 ; a2 = ioreq
- move.l io_device(a2),a3 ; a3 = device
-
- btst #DDB_CONFIGURED,dd_flags(a3) ; configured ?
- beq .unconfigured
- btst #DDB_ONLINE,dd_flags(a3) ; online ?
- beq .offline
-
- ; check ioreq's bufman validity
-
- move.l ios2_buffermanagement(a2),d0
- beq.s .bad ; eeeekh, no bufman ?
- move.l d0,a0
- tst.l bufman_copyfrombuf(a0)
- beq.s .bad ; no routine for writing ?
-
- move.l ios2_DataLength(a2),d1
- tst.b io_flags(a2) ; (test SANA2IOB_RAW) raw packets ?
- bpl.s .cooked
-
- cmp.l #RAWPKT_SIZE,d1
- bls.s .goodlen ; check packet size
- bra.s .toobig
-
- .cooked:
- cmp.l #ETHERPKT_SIZE,d1
- bhi.s .toobig
-
- .goodlen:
- bclr #IOB_QUICK,io_flags(a2) ; must be queued
- move.l exec_base(pc),a6
- lea dd_writelist(a3),a0
- move.l a2,a1
- ifd verbose
- bug <"cnet: CMD_WRITE ior $%08lx added to writelist $%08lx",10>,a1,a0
- endc
- MYDISABLE
- ADDTAIL ; add ioreq to write queue
- MYENABLE
-
- lea dd_txint(a3),a1
- jsr _LVOCause(a6) ; start tx
-
- .done:
- movem.l (sp)+,a2/a3/a6
- rts
-
-
- .unconfigured:
- moveq #S2WERR_NOT_CONFIGURED,d0 ; error, not configured
- move.b #S2ERR_BAD_STATE,io_error(a2)
- bra.s .error
-
- .offline:
- moveq #S2WERR_UNIT_OFFLINE,d0 ; error, device is offline
- move.b #S2ERR_OUTOFSERVICE,io_error(a2)
- bra.s .error
-
- .bad:
- moveq #S2WERR_GENERIC_ERROR,d0 ; error, bad argument
- move.b #S2ERR_BAD_ARGUMENT,io_error(a2)
- bra.s .error
-
- .toobig:
- moveq #S2EVENT_TX,d0 ; return any TX events
- bsr DoEvent
- moveq #0,d0
- move.b #S2ERR_MTU_EXCEEDED,io_error(a2) ; oops! packet too big
-
- .error:
- ifd verbose
- bug <"cnet: write ior $%08lx error %ld",10>,a2,d0
- endc
-
- move.l d0,ios2_wireerror(a2)
- move.l a2,a1
- bsr TermIO
- bra.s .done
-
-
-
- ;==============================================
- ; CMD_FLUSH
- ;==============================================
- ;
- devcmd_flush:
- movem.l a1-a2/a6,-(sp)
- move.l exec_base(pc),a6
- move.l io_device(a1),a2 ; a2 = device
-
- bug <"cnet: CMD_FLUSH ior $%08lx device $%08lx",10>,a1,a2
-
- ifgt 0
- ifd debug
- ifd verbose
- bug <"cnet: delaying...",10>
- move.l #500000,d0
- .wait:
- tst.b $bfe001
- subq.l #1,d0
- bne.s .wait
- endc
- endc
- endc
-
- MYDISABLE
-
- move.l a2,a0
- moveq #IOERR_ABORTED,d0
- moveq #0,d1
- bsr AbortRW
-
- lea dd_eventlist(a2),a0 ; abort all Event requests
- moveq #IOERR_ABORTED,d0
- moveq #0,d1
- bsr AbortList
-
- MYENABLE
- bug <"cnet: CMD_FLUSH done",10>
-
- movem.l (sp)+,a1-a2/a6
- bra TermIO
-
-
-
- ;======================================================================
- ; abortlist(list, errcode, wireerror, execbase)
- ; a0 d0.b d1.l a6
- ;======================================================================
- ;
- ; Aborts all ios2requs in given list with ios2_Error set to errcode
- ; and ios2_wireerror set to wireerror.
- ;
- AbortList:
- movem.l d2-d3/a2,-(sp)
- move.l a0,a2
- move.b d0,d2
- move.l d1,d3
- bra.s .flush
-
- .loop:
- move.l d0,a1
- ;move.b #NT_REPLYMSG,ln_type(a1)
- move.b d2,io_error(a1)
- move.l d3,ios2_wireerror(a1)
- ;bug <"cnet: AbortList ior $%08lx",10>,a1
- jsr _LVOReplyMsg(a6)
- .flush:
- move.l a2,a0
- MYREMHEAD
- bne.s .loop
-
- movem.l (sp)+,d2-d3/a2
- rts
-
-
-
- ;======================================================================
- ; abortrw(device, errcode, wireerror, execbase)
- ; a0 d0.b d1.l a6
- ;======================================================================
- ;
- ; Aborts all pending reads and writes with ios2_Error set to errcode
- ; and ios2_wireerror set to wireerror.
- ;
- AbortRW:
- movem.l d2-d4/a2-a3,-(sp)
- move.l a0,a3
- move.b d0,d2
- move.l d1,d3
-
- move.l dd_bufmanlist(a3),a2
- .reado:
- move.l (a2),d4
- beq.s .flushrest
- bra.s .flushreads
-
- .readloop:
- move.l d0,a1
- ;move.b #NT_REPLYMSG,ln_type(a1)
- move.b d2,io_error(a1)
- move.l d3,ios2_wireerror(a1)
- ;bug <"cnet: AbortRead ior $%08lx",10>,a1
- jsr _LVOReplyMsg(a6) ; abort all Read requests
- .flushreads:
- lea bufman_rxqueue(a2),a0
- MYREMHEAD
- bne.s .readloop
-
- move.l d4,a2
- bra.s .reado
- .flushrest:
-
- lea dd_orphanlist(a3),a0 ; abort all ReadOrphan requests
- move.b d2,d0
- move.l d3,d1
- bsr AbortList
-
- lea dd_writelist(a3),a0 ; abort all Write requests
- move.b d2,d0
- move.l d3,d1
- bsr AbortList
-
- movem.l (sp)+,d2-d4/a2-a3
- rts
-
-
-
- ;==============================================
- ; S2_ONLINE
- ;==============================================
- ;
- ; Try to put device online
- ;
- devcmd_online:
- bug <"cnet: s2_online",10>
-
- move.l a1,-(sp)
- move.l io_device(a1),a0 ; a0 = device
-
- ; This is a workaround for Genesis.. it calls
- ; S2_ONLINE before S2_CONFIGINTERFACE.
- btst #DDB_ONLINE,dd_flags(a0) ; already online ?
- bne.s .done
-
- btst #DDB_CONFIGURED,dd_flags(a0) ; won't go online unless configured!
- beq.s .unconfigured
- btst #DDB_NICUP,dd_flags(a0) ; nic initialised ?
- beq.s .uninit
-
- bclr #DDB_OFFLINE,dd_flags(a0)
- bset #DDB_ONLINE,dd_flags(a0) ; mark being online
-
- move.b dd_rcr(a0),nic_rcr ; set receiver to normal mode
-
- moveq #S2EVENT_ONLINE,D0
- bsr DoEvent ; return any ONLINE events
-
- .done:
- move.l (sp)+,a1
- bra TermIO
-
-
- .unconfigured:
- moveq #S2WERR_NOT_CONFIGURED,d0 ; error, device is not configured
- move.b #S2ERR_BAD_STATE,io_error(a2)
- bra.s .error
-
- .uninit:
- moveq #S2WERR_UNIT_OFFLINE,d0
- move.b #S2ERR_OUTOFSERVICE,io_error(a1)
- .error:
- move.l d0,ios2_wireerror(a1)
- bra.s .done
-
-
-
-
- ;==============================================
- ; S2_OFFLINE
- ;==============================================
- ;
- ; take device offline
- ;
- ;
- devcmd_offline:
- bug <"cnet: s2_offline",10>
-
- movem.l a1/a6,-(sp)
- move.l io_device(a1),a0 ; a0 = device
- bset #DDB_OFFLINE,dd_flags(a0)
- bclr #DDB_ONLINE,dd_flags(a0) ; already offline ?
- beq.s .done
-
- btst #DDB_NICUP,dd_flags(a0)
- beq.s .nicoff
- move.b #DSRC_MON,nic_rcr ; set receiver to monitor mode
- .nicoff:
-
- move.l exec_base(pc),a6
- bug <"cnet: s2_offline **NOT** aborting read/readorphan/write requests!",10>
- ifgt 0
- MYDISABLE
- ; a0=device
- moveq #S2ERR_OUTOFSERVICE,d0
- moveq #S2WERR_UNIT_OFFLINE,d1
- bsr AbortRW
- MYENABLE
- endc
-
- moveq #S2EVENT_OFFLINE,d0
- bsr DoEvent ; return any OFFLINE events
-
- .done:
- movem.l (sp)+,a1/a6
- bra TermIO
-
-
-
- ;==============================================
- ; S2_ONEVENT
- ;==============================================
- ;
- ; queue up event requests
- ;
- ; online/offline return immediately if the conditon is met.
- ;
- devcmd_onevent:
- bug <"cnet: s2_onevent mask $%08lx",10>,ios2_wireerror(a1)
-
- movem.l a1/a3/a6,-(sp)
- move.l io_device(a1),a3 ; a3 = device
-
- ; do we know the requested events?
- move.l ios2_wireerror(a1),d0
- and.l #~(S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE),d0
- bne .unknown
-
- move.l ios2_wireerror(a1),d0
- and.l #S2EVENT_ONLINE,d0 ; waiting for online event ?
- beq.s .noton
- btst #DDB_ONLINE,dd_flags(a3) ; currently online ?
- bne.s .rtn
- bra.s .queue
-
- .noton:
- move.l ios2_wireerror(a1),d0
- and.l #S2EVENT_OFFLINE,d0 ; waiting for offline event ?
- beq.s .queue
- btst #DDB_ONLINE,dd_flags(a3) ; currently offline ?
- bne.s .queue
-
- .rtn:
- bug <"is (on|off)line",10>
- move.l d0,ios2_wireerror(a1) ; return immediately
- ;already! clr.b io_error(a1)
- .term:
- bsr TermIO
- bra.s .done
-
- .queue:
- bug <"queued",10>
- bclr #IOB_QUICK,io_flags(a1) ; must be queued
- move.l exec_base(pc),a6
- lea dd_eventlist(a3),a0
- MYDISABLE
- ADDTAIL ; add ioreq to event queue
- MYENABLE
-
- .done:
- movem.l (sp)+,a1/a3/a6
- rts
-
- .unknown:
- bug <"unknown events requested!",10>
- moveq #S2WERR_BAD_EVENT,d0
- move.b #S2ERR_NOT_SUPPORTED,io_error(a1)
- move.l d0,ios2_wireerror(a1)
- bra.s .term
-
-
-
- ;==============================================
- ; S2_DEVICEQUERY
- ;==============================================
- ;
- devcmd_devicequery:
- bug <"cnet: s2_devicequery",10>
-
- move.l a1,-(sp)
- move.l ios2_statdata(a1),a0 ; a0 = caller's buffer
- move.l (a0),d1 ; d1 = buffer size
- move.l size_supplied(pc),d0
- cmp.l d0,d1 ; enough space to store info?
- bhs.s .get
-
- clr.l S2DQ_SIZESUPPLIED(a0) ; nope!
- .bad:
- moveq #S2WERR_BAD_STATDATA,d0
- move.b #S2ERR_BAD_ARGUMENT,io_error(a1)
- move.l d0,ios2_wireerror(a1)
- bra.s .done
-
- .get:
- lea S2DQ_SIZESUPPLIED(a0),a1
- lea size_supplied(pc),a0
-
- subq.l #4,d0 ; skip bytes_available
- bra.s .copy
- .copyloop:
- move.b (a0)+,(a1)+ ; copy info to caller's buffer
- .copy:
- subq.w #1,d0
- bpl.s .copyloop
-
- .done:
- move.l (sp)+,a1
- bra TermIO
-
-
-
- ;==============================================
- ; S2_GETSTATIONADDRESS
- ;==============================================
- ;
- devcmd_getstationaddress:
- bug <"cnet: s2_getstationaddress",10>
-
- move.l io_device(a1),a0
- move.l a1,-(sp)
- lea dd_stationaddress(a0),a0
- lea ios2_srcaddr(a1),a1 ; source address = station address
- bsr.s .makeit
- subq.l #ETHER_ADDR_SIZE,a0 ; dest address = default address
- bsr.s .makeit
-
- move.l (sp)+,a1
- bra TermIO
-
- .makeit:
- move.l (a0)+,(a1)+
- move.w (a0)+,(a1)+
- clr.w (a1)+
- clr.l (a1)+
- clr.l (a1)+
- rts
-
-
-
- ;==============================================
- ; S2_CONFIGINTERFACE
- ;==============================================
- ;
- ; NOTE: a default station address has already
- ; been set by init_nic
- ;
- devcmd_configinterface:
- bug <"cnet: s2_configinterface",10>
-
- move.l io_device(a1),a0
- bset #DDB_CONFIGURED,dd_flags(a0) ; already configured ?
- bne .already
-
- move.l a6,-(sp)
- move.l exec_base(pc),a6
- MYDISABLE
-
- move.l ios2_srcaddr(a1),d0
- ble .badaddr ; check for valid address
-
- lea dd_stationaddress(a0),a0
- move.l d0,(a0)
- move.w ios2_srcaddr+4(a1),4(a0)
-
- move.b nic_cr,d1 ; remember current command
- delay
- move.b #DSCM_NODMA|DSCM_PG1,nic_cr ; select bank 1
- delay
- move.b (a0)+,nic_par0
- delay
- move.b (a0)+,nic_par1
- delay
- move.b (a0)+,nic_par2
- delay ; set station address
- move.b (a0)+,nic_par3
- delay
- move.b (a0)+,nic_par4
- delay
- move.b (a0),nic_par5
- delay
- move.b d1,nic_cr ; restore command
-
- .done:
- MYENABLE
- move.l (sp)+,a6
- .termit:
- bra TermIO
-
- .badaddr:
- bclr #DDB_CONFIGURED,dd_flags(a0) ; NOT configured!
- moveq #S2WERR_SRC_ADDRESS,d0 ; error, source address bad
- move.b #S2ERR_BAD_ADDRESS,io_error(a1)
- move.l d0,ios2_wireerror(a1)
- bra.s .done
-
- .already
- moveq #S2WERR_IS_CONFIGURED,d0 ; error, already configured
- move.b #S2ERR_BAD_STATE,io_error(a1)
- move.l d0,ios2_wireerror(a1)
- bra.s .termit
-
-
-
- ;==============================================
- ; S2_MULTICAST
- ;==============================================
- ;
- devcmd_multicast:
- bug <"cnet: s2_multicast %08lx%04x",10>,ios2_dstaddr(a1),ios2_dstaddr+2(a1)
-
- btst #0,ios2_dstaddr(a1) ; is dest a multicast address ?
- bne devcmd_write
-
- move.l a1,-(sp)
- moveq #S2EVENT_TX,d0 ; return any TX events
- bsr DoEvent
- move.l (sp)+,a1
-
- moveq #S2WERR_BAD_MULTICAST,d0 ; wasn't a multicast addr
- move.b #S2ERR_BAD_ADDRESS,io_error(a1)
- move.l d0,ios2_wireerror(a1)
- bra TermIO
-
-
-
- ;==============================================
- ; S2_BROADCAST
- ;==============================================
- ;
- devcmd_broadcast:
- bug <"cnet: s2_broadcast",10>
-
- moveq #-1,d0
- move.l d0,ios2_dstaddr+0(a1) ; dest address = BROADCAST (255)
- move.w d0,ios2_dstaddr+4(a1) ; dest address = BROADCAST (255)
-
- bra devcmd_write
-
-
-
- ;============================================
- ; S2_TRACKTYPE
- ;============================================
- ;
- ; This function adds a packet type to the
- ; list of those that are being tracked.
- ;
- devcmd_tracktype:
- bug <"cnet: s2_tracktype %ld",10>,ios2_packettype(a1)
-
- movem.l a2/a3/a6,-(sp)
- move.l exec_base(pc),a6
- move.l a1,a2 ; a2 = ioreq
- move.l io_device(a1),a3
- move.l ios2_packettype(a2),d0 ; d0 = our packet type
-
- MYDISABLE ; lock access to list
- move.l dd_tracklist(a3),a0 ; a0 = 1st entry in list
- bra.s .start
-
- .search:
- cmp.l ss2_ptype(a0),d0 ; = our packet type ?
- beq.s .duperr
- move.l d1,a0
- .start:
- move.l (a0),d1
- bne.s .search ; end of list ?
-
- moveq #ss2_sizeof,d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- jsr _LVOAllocMem(a6) ; allocmem for tracking node
- tst.l d0
- beq.s .nomem
-
- move.l d0,a1 ; a1 = new entry
- move.l ios2_packettype(a2),ss2_ptype(a1) ; set tracking type
- lea dd_tracklist(a3),a0
- ADDTAIL ; add new tracktype node to list
-
- .done:
- MYENABLE ; release lock on lists
- move.l a2,a1
- movem.l (sp)+,a2/a3/a6
- bra TermIO
-
-
- .nomem:
- moveq #S2WERR_NOT_TRACKED,d0
- move.b #S2ERR_NO_RESOURCES,io_error(a2)
- bra.s .error ; error, can't allocate memory!
-
- .duperr:
- moveq #S2WERR_ALREADY_TRACKED,d0
- move.b #S2ERR_BAD_STATE,io_error(a2)
-
- .error:
- move.l d0,ios2_wireerror(a2) ; error, type is tracked already!
- bra.s .done
-
-
-
- ;==============================================
- ; S2_UNTRACKTYPE
- ;==============================================
- ;
- ; This function removes a packet type from the
- ; list of those that are being tracked.
- ;
- devcmd_untracktype:
- bug <"cnet: s2_untracktype %ld",10>,ios2_packettype(a1)
-
- movem.l a2-a3/a6,-(sp)
- move.l exec_base(pc),a6
- move.l a1,a2 ; a2 = ioreq
- move.l io_device(a1),a0
- move.l ios2_packettype(a2),d0 ; d0 = packet type to untrack
-
- MYDISABLE ; lock access to list
- move.l dd_tracklist(a0),a3 ; a3 = 1st entry in tracking list
- bra.s .start
-
- .search:
- cmp.l ss2_ptype(a3),d0 ; found our packet type ?
- beq.s .found
- move.l d1,a3 ; a3 = next entry
- .start:
- move.l (a3),d1
- bne.s .search ; end of list?
- bra.s .error
-
- .found:
- move.l a3,a1
- REMOVE ; remove entry from list
- move.l a3,a1
- moveq #ss2_sizeof,d0
- jsr _LVOFreeMem(a6) ; free entry's memory
-
- .done:
- MYENABLE ; unlock access to list
- move.l a2,a1
- movem.l (sp)+,a2-a3/a6
- bra TermIO
-
-
- .error:
- moveq #S2WERR_NOT_TRACKED,d0 ; error, no tracktype!
- move.b #S2ERR_BAD_STATE,io_error(a2)
- move.l d0,ios2_wireerror(a2)
- bra.s .done
-
-
-
- ;==================================================
- ; S2_GETTYPESTATS
- ;==================================================
- ; This function returns statistics for a specific
- ; type of packet that is being tracked.
- ;
- devcmd_gettypestats:
- bug <"cnet: s2_gettypestats",10>
-
- movem.l a2/a6,-(sp)
- move.l exec_base(pc),a6
- move.l a1,a2 ; a2 = ioreq
- move.l io_device(a1),a0
- move.l ios2_packettype(a2),d0 ; d0 = packettype
-
- MYDISABLE ; lock access to list
- move.l dd_tracklist(a0),a0 ; a0 = 1st entry in tracking list
- bra.s .start
-
- .loop:
- move.l d1,a0 ; a0 = next entry
- .start:
- move.l (a0),d1 ; end of list ?
- beq.s .notfound
- cmp.l ss2_ptype(a0),d0 ; found our track type ?
- bne.s .loop
-
- ; note that both ss2_stats and ios2_statdata are quaranteed to be
- ; word aligned.
- lea ss2_stats(a0),a0
- move.l ios2_statdata(a2),a1
- moveq #s2pts_size/4,d0
- .copystats
- move.l (a0)+,(a1)+ ; copy stats to ioreq
- subq.l #1,d0
- bne.s .copystats
-
- .done:
- MYENABLE ; release lock on list
- move.l a2,a1
- movem.l (sp)+,a2/a6
- bra TermIO
-
- .notfound:
- moveq #S2WERR_NOT_TRACKED,d0
- move.b #S2ERR_BAD_STATE,io_error(a2)
- move.l d0,ios2_wireerror(a2) ; error, couldn't find track type
- bra.s .done
-
-
-
- ;==============================================
- ; S2_GETSPECIALSTATS
- ;==============================================
- ;
- devcmd_getspecialstats:
- bug <"cnet: s2_getspecialstats",10>
-
- movem.l a1-a2,-(sp)
- move.l io_device(a1),a2 ; a2 = unit
- move.l ios2_statdata(a1),a1
- clr.l s2ssh_recordcountsupplied(a1)
- move.l (a1)+,d0 ; check s2ssh_recordcountmax
- beq.s .done
-
- addq.l #1,(a1)+ ; s2ssh_recordcountsupplied++
- move.l a1,a0
- move.l #S2SS_ETHERNET_BADMULTICAST,(a0)+ ; set type }
- move.l dd_badmulticasts(a2),(a0)+ ; set statistic } bad multi
- move.l #multiname,(a0)+ ; set name }
- subq.l #1,d0
- beq.s .done ; want more ?
-
- addq.l #1,-(a1) ; s2ssh_recordcountsupplied++
- move.l #S2SS_ETHERNET_RETRIES,(a0)+ ; set type }
- move.l dd_retries(a2),(a0)+ ; set statistic } retries
- move.l #retryname,(a0)+ ; set name }
-
- .done:
- movem.l (sp)+,a1-a2
- bra TermIO
-
-
-
- ;==============================================
- ; S2_GETGLOBALSTATS
- ;==============================================
- ;
- devcmd_getglobalstats:
- bug <"cnet: s2_getglobalstats",10>
-
- move.l a1,-(sp)
- move.l io_device(a1),a0
-
- ; note that both dd_devicestats and ios2_statdata are quaranteed to be
- ; word aligned.
- ;
- lea dd_devicestats(a0),a0
- move.l ios2_statdata(a1),a1
- moveq #s2ds_size/4,d0
- .copy:
- move.l (a0)+,(a1)+ ; get sana2devicestats
- subq.l #1,d0
- bne.s .copy
-
- move.l (sp)+,a1
- bra TermIO
-
-
-
- ;==========================================================
- ; get_time
- ;==========================================================
- ;
- ; in: a0 = pointer to timeval struct
- ;
- ; get current time_of_day
- ;
- get_time:
- move.l timereq+io_device(pc),d0
- movem.l a2/a6,-(sp)
- beq.s .open ; io_device <> 0 ?
- addq.l #1,d0
- move.l a0,a2
- bne.s .gotdev ; io_device <> -1 ?
- .open:
- move.l exec_base(pc),a6
- lea timerdevname(pc),a0
- lea timereq(pc),a1
- moveq #UNIT_VBLANK,d0
- move.b #NT_MESSAGE,ln_type(a1)
- moveq #0,d1
- move.w #iotv_size,mn_length(a1)
- jsr _LVOOpenDevice(a6)
- tst.l d0
- bne.s .done
-
- .gotdev:
- lea timereq(pc),a1
- move.l io_device(a1),a6
- move.l a2,a0
- jsr _LVOGetSysTime(a6)
- .done:
- movem.l (sp)+,a2/a6
- rts
-
-
-
- ;==============================================
- ; S2_ADDMULTICASTADDRESS
- ;==============================================
- ;
- devcmd_addmulticast:
- bug <"cnet: s2_addmulticastaddress %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1)
-
- move.l ios2_srcaddr+4(a1),-(sp) ; lower = upper !
- move.l ios2_srcaddr(a1),-(sp)
- move.l ios2_srcaddr+4(a1),-(sp)
- move.l ios2_srcaddr(a1),-(sp)
-
- addmcast:
- movem.l a2-a4/a6,-(sp)
- move.l a6,a3 ; a3 = device
- move.l exec_base(pc),a6
- move.l a1,a4 ; a4 = ioreq
-
- bsr.s addmcastrange
-
- move.l a4,a1
- movem.l (sp)+,a2-a4/a6
- lea 4*4(sp),sp
- bra TermIO
-
-
-
- ;==============================================
- ; S2_ADDMULTICASTADDRESSES
- ;==============================================
- ;
- devcmd_addmulticasts:
- bug <"cnet: s2_addmulticastaddresses %08lx%04x - %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1),ios2_dstaddr(a1),ios2_dstaddr+2(a1)
-
- move.l ios2_dstaddr+4(a1),-(sp) ; upper
- move.l ios2_dstaddr(a1),-(sp)
- move.l ios2_srcaddr+4(a1),-(sp) ; lower
- move.l ios2_srcaddr(a1),-(sp)
- bra.s addmcast
-
-
-
-
- AMCRO EQU 4+(4*4)
- addmcastrange:
- btst #0,AMCRO+0+0(sp) ; is src a multicast address ?
- beq.s .badmcast
- btst #0,AMCRO+8+0(sp) ; is dst a multicast address ?
- beq.s .badmcast
-
- lea dd_multicastssema(a3),a0
- jsr _LVOObtainSemaphore(a6) ; lock access to list
- move.l dd_multicasts(a3),a0 ; a0 = first entry in multicast list
- bra.s .getmulti
-
- .check:
- move.l AMCRO+0+0(sp),d0
- cmp.l mcastar_loweraddr(a0),d0
- bne.s .next
- move.w AMCRO+0+4(sp),d0
- cmp.w mcastar_loweraddr+4(a0),d0
- bne.s .next
- move.l AMCRO+8+0(sp),d0 ; is our address in an existing entry ?
- cmp.l mcastar_upperaddr(a0),d0
- bne.s .next
- move.w AMCRO+8+4(sp),d0
- cmp.w mcastar_upperaddr+4(a0),d0
- bne.s .next
-
- addq.l #1,mcastar_count(a0) ; added same address again
- ifd debug
- move.l mcastar_count(a0),d0
- bug <"cnet: mcast node $%lx count=%ld",10>,a0,d0
- endc
- bra .unlock
-
- .next:
- move.l d1,a0 ; get next node in list
- .getmulti:
- move.l (a0),d1 ; end of list ?
- bne.s .check
-
- moveq #mcastar_sizeof,d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- jsr _LVOAllocMem(a6) ; allocate memory for multicast entry
- tst.l d0
- beq.s .nomem
-
- move.l d0,a1 ; a1 = new entry
- move.w #1,mcastar_count+2(a1) ; count = 1
- move.l AMCRO+0+0(sp),mcastar_loweraddr(a1)
- move.w AMCRO+0+4(sp),mcastar_loweraddr+4(a1)
- move.l AMCRO+8+0(sp),mcastar_upperaddr(a1)
- move.w AMCRO+8+4(sp),mcastar_upperaddr+4(a1)
- bug <"cnet: new mcast node at $%08lx",10>,a1
- lea dd_multicasts(a3),a0
- ADDTAIL ; add to list
- move.l a3,a0
- bsr update_multicasts ; update multicasts in nic
-
- .unlock
- lea dd_multicastssema(a3),a0
- jmp _LVOReleaseSemaphore(a6) ; release lock on list
-
-
- .badmcast:
- moveq #S2WERR_BAD_MULTICAST,d0
- move.b #S2ERR_BAD_ADDRESS,io_error(a4)
- move.l d0,ios2_wireerror(a4) ; invalid multicast address
- rts
-
-
- .nomem:
- moveq #S2WERR_GENERIC_ERROR,d0
- move.b #S2ERR_NO_RESOURCES,io_error(a4)
- move.l d0,ios2_wireerror(a4)
- bra.s .unlock
-
-
-
- ;==============================================
- ; S2_DELMULTICASTADDRESS
- ;==============================================
- ;
- devcmd_delmulticast:
- bug <"cnet: s2_delmulticastaddress %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1)
-
- move.l ios2_srcaddr+4(a1),-(sp) ; lower = upper !
- move.l ios2_srcaddr(a1),-(sp)
- move.l ios2_srcaddr+4(a1),-(sp)
- move.l ios2_srcaddr(a1),-(sp)
-
- remmcast:
- movem.l a2-a4/a6,-(sp)
- move.l a6,a3 ; a3 = device
- move.l exec_base(pc),a6
- move.l a1,a4 ; a4 = ioreq
-
- bsr.s delmcastrange
-
- move.l a4,a1
- movem.l (sp)+,a2-a4/a6
- lea 4*4(sp),sp
- bra TermIO
-
-
-
- ;==============================================
- ; S2_DELMULTICASTADDRESSES
- ;==============================================
- ;
- devcmd_delmulticasts:
- bug <"cnet: s2_delmulticastaddresses %08lx%04x - %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1),ios2_dstaddr(a1),ios2_dstaddr+2(a1)
-
- move.l ios2_dstaddr+4(a1),-(sp) ; upper
- move.l ios2_dstaddr(a1),-(sp)
- move.l ios2_srcaddr+4(a1),-(sp) ; lower
- move.l ios2_srcaddr(a1),-(sp)
- bra.s remmcast
-
-
-
- DMCRO EQU 4+(4*4)
- delmcastrange:
- lea dd_multicastssema(a3),a0
- jsr _LVOObtainSemaphore(a6) ; lock access to list
- move.l dd_multicasts(a3),a2 ; a2 = first entry in multicast list
- bra.s .getmulti
-
- .check:
- move.l DMCRO+0+0(sp),d0
- cmp.l mcastar_loweraddr(a2),d0
- bne.s .next
- move.w DMCRO+0+4(sp),d0
- cmp.w mcastar_loweraddr+4(a2),d0
- bne.s .next
- move.l DMCRO+8+0(sp),d0 ; is it our address ?
- cmp.l mcastar_upperaddr(a2),d0
- bne.s .next
- move.w DMCRO+8+4(sp),d0
- cmp.w mcastar_upperaddr+4(a2),d0
- bne.s .next
-
- subq.l #1,mcastar_count(a2) ; one less count
- bne.s .done
-
- bug <"cnet: mcast entry $%08lx removed",10>,a2
- move.l a2,a1
- REMOVE ; remove entry from list
- move.l a2,a1
- moveq #mcastar_sizeof,d0
- jsr _LVOFreeMem(a6) ; free memory used by entry
-
- move.l a3,a0
- bsr update_multicasts ; update multicasts in nic
- bra.s .done
-
- .next:
- move.l d1,a2 ; get next node in list
- .getmulti:
- move.l (a2),d1 ; end of list ?
- bne.s .check
-
- moveq #S2WERR_BAD_MULTICAST,d0
- move.b #S2ERR_BAD_STATE,io_error(a4)
- move.l d0,ios2_wireerror(a4)
-
- .done:
- lea dd_multicastssema(a3),a0
- jmp _LVOReleaseSemaphore(a6) ; release lock on list
-
-
-
-
- ;================================================================
- ; Update Multicasts
- ;================================================================
- ;
- ; calculate multicast hash table and send it to nic
- ;
- ; as of 1.2beta4 multicasts can be a address range, also single
- ; addresses are defined with lower = upper.
- ;
- ; update_multicasts(device)
- ; a0
- update_multicasts:
- movem.l d2-d4/a2,-(sp)
- move.l dd_multicasts(a0),a2
- lea mcastaddr(pc),a0
- clr.l (a0)+ ; clear all multicast bits
- clr.l (a0)+
-
- subq.l #8,sp ; temp for address
-
- .next:
- move.l (a2),d4
- beq.s .update ; end of list ?
- move.l mcastar_loweraddr(a2),(sp)
- move.w mcastar_loweraddr+4(a2),4(sp)
-
- .hashall:
- moveq #-1,d0 ; initial crc seed
- moveq #6,d1 ; 6 bytes in ethernet address
- move.l sp,a0 ; data to crc
-
- .nextbyte:
- move.b (a0)+,d3 ; get next data byte
- moveq #8,d2 ; 8 bits in byte
-
- .nextbit:
- lsl.l #1,d0 ; crc << 1
- bcc.s .crcnot1
- lsr.b #1,d3 ; data >> 1
- bcc.s .xor
- bra.s .skipnext
- .crcnot1:
- lsr.b #1,d3 ; data >> 1
- bcc.s .skipnext
- .xor:
- eor.l #$04c11db7,d0 ; crc = crc XOR polynomial
- .skipnext:
- subq.l #1,d2
- bne.s .nextbit
-
- subq.l #1,d1
- bne.s .nextbyte
-
- rol.l #6,d0
- lea mcastaddr(pc),a0
- and.w #%0000000000111111,d0 ; isolate upper 6 bits
- move.w d0,d1
- and.b #%00000111,d0 ; d0 = bit in byte
- lsr.w #3,d1 ; d1 = byte offset
- bset d0,0(a0,d1.w) ; set bit for hashed multicast address
-
-
- move.l mcastar_upperaddr+2(a2),d0
- move.w mcastar_upperaddr(a2),d1
- cmp.l 2(sp),d0 ; all done with this range ?
- bne.b .still
- cmp.w (sp),d1
- beq.b .donext ; all done with this range ?
- .still:
- ; increment to next address...
- addq.l #1,2(sp)
- bne.b .hashall ; did we overflow 32bit ?
- addq.w #1,(sp) ; 48bit add fix
- bra.s .hashall
-
- .donext:
- move.l d4,a2
- bra.s .next
-
- .update:
- addq.l #8,sp
-
- bsr put_multi ; update multicast bits in nic
-
- movem.l (sp)+,d2-d4/a2
- rts
-
-
-
-
- ifgt 0 ; this stuff inlined
-
- ;==============================================================
- ; hash multicast address
- ;==============================================================
- ; The nic does not compare multicast addresses directly, but
- ; instead uses a bitfield of 64 bits - each bit corresponds
- ; to a 6 bit hash code for the multicast address. If the bit
- ; is set then any multicast address that matches the hash code
- ; will be accepted.
- ;
- ; The hash code is generated by taking the upper 6 bits of the
- ; 32 bit crc of the multicast address.
- ;
- ; hash_multi(address)
- ; a0
- ;
- hash_multi:
- moveq #-1,d0 ; initial crc seed
- moveq #6,d1 ; 6 bytes in ethernet address
-
- bsr.s calc_crc ; calculate crc for this multicast address
-
- rol.l #6,d0
- lea mcastaddr(pc),a0
- and.w #%0000000000111111,d0 ; isolate upper 6 bits
- move.w d0,d1
- and.b #%00000111,d0 ; d0 = bit in byte
- lsr.w #3,d1 ; d1 = byte offset
- bset d0,0(a0,d1.w) ; set bit for hashed multicast address
- rts
-
-
-
- ;===========================================================================
- ; Calculate 32 bit crc
- ;===========================================================================
- ;
- ; - for each bit: if (crcbit=1 XOR databit=1) then crc=(crc XOR polynomial).
- ; - polynomial is correct when data bits range 0-x, crc bits range 31-0.
- ; - crc wraps at 32 bits.
- ;
- ; crc = calc_crc(data, seed, bytelength)
- ; d0.l a0 d0.l d1.l
- ;
- calc_crc:
- movem.l d2/d3,-(sp)
-
- .nextbyte:
- move.b (a0)+,d3 ; get next data byte
- moveq #8,d2 ; 8 bits in byte
-
- .nextbit:
- lsl.l #1,d0 ; crc << 1
- bcc.s .crcnot1
- lsr.b #1,d3 ; data >> 1
- bcc.s .xor
- bra.s .next
- .crcnot1:
- lsr.b #1,d3 ; data >> 1
- bcc.s .next
- .xor:
- eor.l #$04c11db7,d0 ; crc = crc XOR polynomial
- .next:
- subq.l #1,d2
- bne.s .nextbit
-
- subq.l #1,d1
- bne.s .nextbyte
-
- movem.l (sp)+,d2/d3
- rts
-
- endc
-
-
-
- ;==============================================================
- ; Put Multicast address bitfield into NIC registers
- ;==============================================================
- ;
- put_multi:
- move.l a6,-(sp)
- move.l exec_base(pc),a6
- lea mcastaddr(pc),a0
- MYDISABLE
- delay
- move.b nic_cr,d0 ; save old command
- delay
- move.b #DSCM_PG1|DSCM_NODMA|DSCM_STOP,nic_cr ; select page 1
- delay
- move.b (a0)+,nic_mar0
- delay
- move.b (a0)+,nic_mar1
- delay
- move.b (a0)+,nic_mar2
- delay
- move.b (a0)+,nic_mar3
- delay ; put Multicast bits
- move.b (a0)+,nic_mar4
- delay
- move.b (a0)+,nic_mar5
- delay
- move.b (a0)+,nic_mar6
- delay
- move.b (a0),nic_mar7
- delay
- move.b d0,nic_cr ; restore old command
- MYENABLE
- move.l (sp)+,a6
- rts
-
-
-
- ;=========================================================
- ; commands not supported
- ;=========================================================
- ;
- devcmd_nosupport:
- bug <"cnet: Unsupported command %d",10>,io_command-2(a1)
-
- moveq #S2WERR_GENERIC_ERROR,d0
- move.b #S2ERR_NOT_SUPPORTED,io_error(a1)
- move.l d0,ios2_wireerror(a1)
- bra TermIO
-
-
-
- ;==========================================================
- ; doevent([device,] events)
- ; a0 d0
- ;==========================================================
- ;
- ; called when an 'important' event occurs
- ;
- DoEvent:
- bug <"cnet: doevent $%08lx ...">,d0
-
- movem.l d2-d3/a2/a6,-(sp)
- move.l exec_base(pc),a6
- move.l d0,d2
- move.l me_myself(pc),a0 ; get global pointer to self...
- MYDISABLE ; lock eventlist
-
- move.l dd_eventlist(a0),a2 ; get first ioreq
- bra.s .start
-
- .loop:
- move.l ios2_wireerror(a2),d0
- and.l d2,d0 ; ioreq for our events?
- beq.s .next
-
- move.l d0,ios2_wireerror(a2) ; set the actual events
- move.l a2,a1
- REMOVE ; remove ioreq from list
- move.b #NT_REPLYMSG,ln_type(a2)
- move.l a2,a1
- bug <"cnet: returned eventreq $%lx",10>,a1
- jsr _LVOReplyMsg(a6) ; send reply to ioreq owner
-
- .next:
- move.l d3,a2 ; next ioreq
-
- .start:
- move.l (a2),d3 ; last ioreq ?
- bne.s .loop
-
- MYENABLE ; unlock eventlist
- bug <10,"cnet: doevent done",10>
- movem.l (sp)+,d2-d3/a2/a6
- rts
-
-
-
- ;==================================================================
- ; RemoteRead(buffer, nicbuffer, length)
- ; a1 d0.w d1.w
- ;==================================================================
- ;
- ; Get a copy of data stored in the network card's onboard RAM.
- ;
- ; buffer = Amiga RAM
- ;
- ; nicbuffer = 16 bit address in card memory
- ;
- CNOP 0,4
- ;RemoteRead:
- REMOTEREAD MACRO
-
- ifd turboio
-
- addq.w #3,d1 ; bump up count to even value
- and.w #-4,d1
- delay
- swap d1
- move.b nic_cr,d1 ; save old command
- swap d1
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
- delay
- move.b d1,nic_rbcr0 ; set count.lo
- ror.w #8,d1
- delay
- move.b d1,nic_rbcr1 ; set count.hi
- delay
- move.b d0,nic_rsar0 ; set address.lo
- ror.w #8,d0
- delay
- move.b d0,nic_rsar1 ; set address.hi
- delay
- move.b #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
- ror.w #8,d1
- move.w d1,d0
- and.w #%0000000000111100,d1
- lea nic_data,a0
- lsr.w #1,d1
- lsr.w #6,d0
- neg.w d1
- jmp .rr_startread(pc,d1.w)
- .rr_dmaread:
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- .rr_startread:
- subq.w #1,d0
- bpl.s .rr_dmaread
-
- move.b #DSIS_RDC,nic_isr ; Remote DMA Complete
- swap d1
- delay
- move.b d1,nic_cr ; restore old command
- ;rts
-
- else
-
- addq.w #1,d1 ; bump up count to even value
- and.w #-2,d1
- delay
- swap d1
- move.b nic_cr,d1 ; save old command
- swap d1
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
- delay
- move.b d1,nic_rbcr0 ; set count.lo
- ror.w #8,d1
- delay
- move.b d1,nic_rbcr1 ; set count.hi
- delay
- move.b d0,nic_rsar0 ; set address.lo
- ror.w #8,d0
- delay
- move.b d0,nic_rsar1 ; set address.hi
- delay
- move.b #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
- ror.w #8,d1
- move.w d1,d0
- and.w #%0000000000011110,d0
- lea nic_data,a0
- neg.w d0
- lsr.w #5,d1
- jmp .rr_startread(pc,d0.w)
- .rr_dmaread:
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- .rr_startread:
- subq.w #1,d1
- bpl.s .rr_dmaread
-
- move.b #DSIS_RDC,nic_isr ; Remote DMA Complete
- swap d1
- delay
- move.b d1,nic_cr ; restore old command
- ;rts
-
- endc
- ENDM
-
-
- ;=================================================================
- ; RemoteWrite( buffer, nicbuffer, count )
- ; a1 d0.w d1.w
- ;=================================================================
- ;
- ; Puts data into the network card's onboard RAM
- ;
- ; buffer = Amiga memory
- ;
- ; nicbuffer = 16 bit address in card RAM
- ;
- ;
- CNOP 0,4
- ;RemoteWrite:
- REMOTEWRITE MACRO
- ifd turboio
-
- addq.w #3,d1
- and.w #-4,d1 ; bump up count to even value
- swap d1
- delay
- move.b nic_cr,d1 ; save old command
- swap d1
- delay
- move.b #DSIS_RDC,nic_isr ; remote DMA complete
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
- delay
- move.b d0,nic_rsar0 ; set address.lo
- lsr.w #8,d0
- delay
- move.b d0,nic_rsar1 ; set address.hi
- delay
- move.b d1,nic_rbcr0 ; set count.lo
- ror.w #8,d1
- delay
- move.b d1,nic_rbcr1 ; set count.hi
- delay
- move.b #DSCM_START|DSCM_RWRITE,nic_cr ; request remote write
- ror.w #8,d1
-
- ; write the etherpacket header & prepare for the copy loop.
- lea nic_data,a0
- sub.w #ether_data+2,d1
- move.l txbuffer(pc),(a0)
- move.w d1,d0
- move.l txbuffer+4(pc),(a0)
- and.w #%0000000000111100,d1
- move.l txbuffer+8(pc),(a0)
- lsr.w #1,d1
- move.w txbuffer+12(pc),(a0)
- lsr.w #6,d0
- neg.w d1
- move.w (a1)+,(a0)
- jmp .rw_startwrite(pc,d1.w)
- .rw_dmawrite:
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- move.l (a1)+,(a0)
- .rw_startwrite:
- subq.w #1,d0
- bpl.s .rw_dmawrite
-
- move.w #30000,d0 ; set timeout
- .rw_check:
- delay
- move.b nic_isr,d1 ; wait for remote DMA complete
- and.b #DSIS_RDC,d1
- dbne d0,.rw_check
-
- ; d0.w < 0 send timed out
- ; d0.w >= 0 send succeeded
-
- delay
- move.b #DSIS_RDC,nic_isr ; Remote DMA complete
- swap d1
- delay
- move.b d1,nic_cr ; restore old command
- ;rts
-
- else
-
- addq.w #1,d1
- and.w #-2,d1 ; bump up count to even value
- swap d1
- delay
- move.b nic_cr,d1 ; save old command
- swap d1
- delay
- move.b #DSIS_RDC,nic_isr ; remote DMA complete
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
- delay
- move.b d0,nic_rsar0 ; set address.lo
- lsr.w #8,d0
- delay
- move.b d0,nic_rsar1 ; set address.hi
- delay
- move.b d1,nic_rbcr0 ; set count.lo
- ror.w #8,d1
- delay
- move.b d1,nic_rbcr1 ; set count.hi
- delay
- move.b #DSCM_START|DSCM_RWRITE,nic_cr ; request remote write
-
- ; write the etherpacket header & prepare for the copy loop.
- lea nic_data,a0
- ror.w #8,d1
- move.w txbuffer(pc),(a0)
- sub.w #ether_data,d1
- move.w txbuffer+2(pc),(a0)
- move.w d1,d0
- move.w txbuffer+4(pc),(a0)
- move.w txbuffer+6(pc),(a0)
- and.w #%0000000000011110,d1
- move.w txbuffer+8(pc),(a0)
- lsr.w #5,d0
- move.w txbuffer+10(pc),(a0)
- neg.w d1
- move.w txbuffer+12(pc),(a0)
- jmp .rw_startwrite(pc,d1.w)
- .rw_dmawrite:
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- move.w (a1)+,(a0)
- .rw_startwrite:
- subq.w #1,d0
- bpl.s .rw_dmawrite
-
- move.w #30000,d0 ; set timeout
- .rw_check:
- delay
- move.b nic_isr,d1 ; wait for remote DMA complete
- and.b #DSIS_RDC,d1
- dbne d0,.rw_check
-
- ; if d0.w<0 timed out
- ; if d0.w>=0 succeeded
-
- delay
- move.b #DSIS_RDC,nic_isr ; Remote DMA complete
- swap d1
- delay
- move.b d1,nic_cr ; restore old command
- ;rts
-
- endc
- ENDM
-
-
-
- ;=========================================================
- ; reset_nic()
- ;=========================================================
- ;
- reset_nic:
- delay
- move.b nic_rst,d0 ; start reset pulse
- delay
- move.b d0,nic_rst ; end reset pulse
- delay
- move.b #DSCM_NODMA|DSCM_STOP,nic_cr ; stop controller
- bsr.s delay1500 ; wait 1.5mS
- move.b #$ff,nic_isr ; clear all nic ints
- rts
-
-
- ;======================
- ; delay approx 1.5mS
- ;======================
- ;
- delay1500:
- move.l d0,-(sp)
- move.w #1500,d0
- .loop:
- tst.b $bfe001 ; wait 1uS
- dbf d0,.loop
- move.l (sp)+,d0
- rts
-
-
-
- ;========================================================================
- ; init_nic(device)
- ; a1
- ;========================================================================
- ;
- ; Set up the network card for online operation. We also get the hardware
- ; station address from the nic's ROM.
- ;
- init_nic:
- movem.l d2/a5/a6,-(sp)
- move.l exec_base(pc),a6
- move.l a1,a5 ; a5 = device data
- MYDISABLE ; ignore ints while setting up
- btst #DDB_NICUP,dd_flags(a5)
- bne .ok ; already initialised ?
-
- move.b #DSDC_WTS|DSDC_FT1|DSDC_BMS,dd_dcr(a5) ; Word Xfer, FIFO, Burst
- move.b #DSRC_AB|DSRC_AM,dd_rcr(a5) ; accept broadcast & multicast
- btst #DDB_PROM,dd_flags2(a5)
- beq.s .notprom ; if promiscuous..
- or.b #DSRC_SEP|DSRC_PRO|DSRC_AR,dd_rcr(a5) ; ..accept all packets
- .notprom:
-
- move.b #INTMASK,dd_imr(a5) ; accept useful interrupts
- bsr reset_nic ; reset the controller
- delay
- move.b nic_cr,d0 ; get command
- cmp.b #DSCM_NODMA|DSCM_STOP,d0
- bne .error1 ; correct response ?
-
- delay
- move.b dd_dcr(a5),nic_dcr ; set data configuration register
- delay
- move.b #0,nic_rbcr0 ; clear remote byte count
- delay
- move.b #0,nic_rbcr1 ; ''
- delay
- move.b #DSRC_MON,nic_rcr ; set rx to monitor mode
- delay
- move.b #DSTC_LB0,nic_tcr ; set tx to loopback mode 1
- delay
- move.b #(RBUFEND/256)-1,nic_bnry ; set boundary page
- delay
- move.b #RBUF/256,nic_pstart ; set start of rx ring buffer
- delay
- move.b #RBUFEND/256,nic_pstop ; set end of rx ring buffer
- delay
- move.b #$ff,nic_isr ; clear all interrupts
- delay
- move.b #0,nic_imr ; no interrupts allowed
- delay
- move.b nic_rsr,d0
- delay
- move.b nic_ncr,d0
- delay
- move.b nic_cntr0,d0 ; read status registers
- delay
- move.b nic_cntr1,d0
- delay
- move.b nic_cntr2,d0
- delay
- move.b #ETHER_ADDR_SIZE*2,nic_rbcr0 ; byte count low = (words)
- delay
- move.b #0,nic_rbcr1 ; byte count high = 0
- delay
- move.b #0,nic_rsar0 ; remote start addr low = 0 (ROM)
- delay
- move.b #0,nic_rsar1 ; remote start addr high = 0 (ROM)
- delay
- move.b #DSCM_RREAD,nic_cr ; start remote read to get
- delay ; station address from ROM
- lea dd_romstationaddress(a5),a0
-
- moveq #ETHER_ADDR_SIZE,d0
- .getaddr:
- move.b nic_data,(a0)+ ; get ROM station address
- subq.l #1,d0 ; NOTE: 'move.b' as ROM is 8 bit
- bne.s .getaddr
-
- move.w #30000,d1
- .waitloop:
- delay
- move.b nic_isr,d0
- and.b #DSIS_RDC,d0 ; wait for remote DMA complete
- dbne d1,.waitloop
-
- tst.w d1
- bmi .error2 ; error if timed out
- delay
- move.b #DSIS_RDC,nic_isr ; clear remote DMA complete int
-
- lea dd_romstationaddress(a5),a0
- tst.b (a0)
- bmi.s .badaddr ; good station address ?
-
- move.l 2(a0),d0
- beq.s .badaddr
- cmp.l #-1,d0
- bne.s .gotstation
- .badaddr:
- bug <"cnet: bad station address %08lx%04lx, using default",10>,(a0),2(a0)
- lea default_address(pc),a0
- .gotstation:
- bug <"cnet: station address set to %08lx%04lx",10>,(a0),2(a0)
-
- lea dd_stationaddress(a5),a1
- move.l (a0)+,(a1)+ ; copy address to device data
- move.w (a0)+,(a1)+
-
- lea dd_stationaddress(a5),a0
- delay
- move.b #DSCM_NODMA|DSCM_PG1|DSCM_STOP,nic_cr ; select bank 1
- delay
- move.b (a0)+,nic_par0
- delay
- move.b (a0)+,nic_par1
- delay
- move.b (a0)+,nic_par2
- delay ; set station address
- move.b (a0)+,nic_par3
- delay
- move.b (a0)+,nic_par4
- delay
- move.b (a0),nic_par5
- delay
- move.b #RBUF/256,nic_curr ; set current page for rx
- move.b #DSCM_NODMA|DSCM_START,d0
- delay
- move.b d0,nic_cr ; start controller
- delay
- cmp.b nic_cr,d0
- bne .error3 ; command accepted ?
-
- bsr put_multi ; load multicast registers
-
- delay
- move.b dd_rcr(a5),nic_rcr ; normal rx mode
- delay
- move.b #0,nic_tcr ; loopback mode off
- delay
- move.b #TBUF/256,nic_tpsr ; init tx start page
- delay
- move.b #$ff,nic_isr ; clear all interrupts
- delay
- move.b dd_imr(a5),nic_imr ; enable nic interrupts
-
- bset #DDB_NICUP,dd_flags(a5) ; nic is initialised
-
- .ok:
- lea dd_devicestats+s2ds_laststart(a5),a0
- bsr get_time ; record start time_of_day
- bug <"cnet: init_nic OK",10>
- moveq #0,d0 ; return OK
-
- .done:
- MYENABLE ; allow interrupt processing
- movem.l (sp)+,d2/a5/a6
- rts
-
-
- .error1:
- bug <"cnet: failed reset, card not compatible?",10>
- bra.s .bad
-
- .error2:
- bug <"cnet: DMA timeout getting station address!",10>
- bra .reset
-
- .error3:
- bug <"cnet: failed to start controller, card faulty?",10>
-
- .reset:
- bsr reset_nic ; reset nic after malfunction
- .bad:
-
- moveq #S2EVENT_ERROR|S2EVENT_HARDWARE,d0
- bsr DoEvent
- moveq #-1,d0 ; return error
- bra .done
-
-
-
- ;--------------------------------------------------------
- ; kill_nic(device)
- ; a1
- ;--------------------------------------------------------
- ;
- kill_nic:
- bug <"cnet: kill_nic",10>
-
- move.l a6,-(sp)
- move.l exec_base(pc),a6
- MYDISABLE
-
- bclr #DDB_NICUP,dd_flags(a1)
- beq.s .done ; already killed ?
- bsr reset_nic ; reset controller
- delay
- move.b #DSRC_MON,nic_rcr ; set rx to monitor mode
- delay
- move.b #DSTC_LB0,nic_tcr ; set tx to loopback mode
- .done:
-
- MYENABLE
- move.l (sp)+,a6
- rts
-
-
-
- ;========================================================
- ; txintcode(device)
- ; a1
- ;========================================================
- ;
- ; send packets to network card. packets will be put
- ; into the card's onboard 16 bit ram, and then
- ; transmitted to the wire.
- ;
- ; scratch: d0-d1, a0-a1, and a5 (softint must preserve a6!)
- ;
- txintcode:
- movem.l d2-d4/a2-a3/a6,-(sp)
- move.l exec_base(pc),a6
- move.l a1,a5 ; a5 = device
-
- .next:
- btst #DDB_TX,dd_flags(a5) ; quit if tx in progress (status int
- bne.s .done ; will restart us when tx complete)
-
- lea dd_writelist(a5),a0
- MYREMHEAD ; remove top ioreq
- bne.s .gotreq ; any ioreqs to process?
-
- .done:
- movem.l (sp)+,d2-d4/a2-a3/a6
- moveq #0,d0
- rts
-
-
- .gotreq:
- move.l d0,a3 ; a3 = ioreq
-
- lea txbuffer(pc),a1 ; a1 = our internal packet buffer
- move.l ios2_buffermanagement(a3),a2
- move.l ios2_datalength(a3),d4 ; default: raw packet's full length
- move.l ios2_packettype(a3),d3 ; d3 = packettype (must be in d3 in non-raw too!!!)
- tst.b io_flags(a3) ; (test SANA2IOB_RAW) raw packets?
- bmi.s .send
-
- ; ok. it's not raw packet so we need to build etherheader for it.
- ; first destination and source addresses then packet type. easy!
-
- lea ios2_dstaddr(a3),a0 ; dstaddress
- move.l (a0)+,(a1)+
- move.w (a0)+,(a1)+
- lea dd_stationaddress(a5),a0 ; from address
- move.l (a0)+,(a1)+
- move.w (a0)+,(a1)+
- move.w d3,(a1)+ ; insert packettype into packet
- add.w #ether_data,d4 ; d4 = length of header + data
-
-
- .send:
- ; Do we have the tag for DMA?
- lea bufman_dmacopyfrombuf32(a2),a2
- move.l a1,d2 ; d2 = where to copyfrom
- move.l (a2)+,d0
- beq.s .nodma
-
- ; Ask for the DMA address
- move.l d0,a1
- move.l ios2_data(a3),a0 ; a0=abstract magic cookie ios2_Data
- jsr (a1)
- tst.l d0 ; dma possible?
- move.l d0,a1
- ; If dma is possible we now have the direct application buffer
- ; in a1.. and we can use that directly with RemoteWrite! cool.
- ifd verbose
- tst.l d0
- beq.s .v1_nodma
- bug <"cnet: using DMA write from $%08lx!",10>,a1
- tst.l d0
- .v1_nodma:
- endc
- bne.s .copyok ; do it with DMA?
-
-
- .nodma:
- ; Ohwell, the caller doesn't support DMA transfer, so lets fall
- ; back to regular copyfrom.
-
- move.l d2,a0 ; a0=to (contiguous)
- move.l ios2_data(a3),a1 ; a1=from (abstract)
- move.l (a2),a2 ; get bufman_copyfrombuf
- move.l ios2_datalength(a3),d0 ; d0=n
- jsr (a2)
- tst.l d0
- beq .copyfromfail ; oh fuck.. copyfrombuf failed!
-
- ; we can return the ioreq now!
- move.l a3,a1
- sub.l a3,a3
- bsr TermIO ; finish IOrequest
-
- lea txbuffer+ether_data(pc),a1 ; non-DMA so use txbuffer for copy!!
- .copyok:
-
- moveq #ETHER_MIN_LEN,d0
- cmp.l d0,d4
- bge.s .min ; d4 adjusted to legal packet size
- move.l d0,d4
- .min:
-
- ifd verbose
- move.l a1,-(sp)
- moveq #0,d1
- move.w txbuffer+ether_type(pc),d1
- bug <"cnet: wrpkt %08lx%04lx >> %08lx%04lx ">,txbuffer+6(pc),txbuffer+8(pc),txbuffer(pc),txbuffer+2(pc)
- cmp.w #1500,d1
- bhs.s .type
- bug <"(IEEE802.3)len %ld, ">,d1
- bra.s .bytes
- .type:
- bug <"type %ld, ">,d1
- .bytes:
- bug <"%ld bytes",10>,d4
- moveq #-ether_data,d0 ; show only the data
- add.l d4,d0
- bsr showpkt
- move.l (sp)+,a1
- endc
-
-
- ; copy the transfer buffer to cards memory
-
- move.w #TBUF,d0
- move.w d4,d1
- ; a1 = txbuffer (or DMA buffer)
- ;bsr RemoteWrite ; put packet into nic tx buffer
- REMOTEWRITE
- tst.w d0
- bmi.s .xmiterr
-
-
-
- ; now really start the transfer:
-
- MYDISABLE ; disable interrupts during tx setup
- bset #DDB_TX,dd_flags(a5) ; set our "buffer full" flag
- delay
- move.b d4,nic_tbcr0 ; set tx byte count lo
- ror.w #8,d4
- delay
- move.b d4,nic_tbcr1 ; set tx byte count hi
- ror.w #8,d4
- delay
- move.b #DSCM_NODMA|DSCM_TRANS|DSCM_START,nic_cr ; start tx
- MYENABLE ; enable interrupts
-
- ; update statistics:
-
- move.l dd_tracklist(a5),a0
- .getstats:
- move.l (a0),d2 ; tracking packettypes ?
- beq.s .statsdone
- cmp.l ss2_ptype(a0),d3 ; stats entry for our type ?
- beq.s .gotstats
- move.l d2,a0 ; try next stats entry
- bra.s .getstats
-
- .gotstats:
- add.l d4,ss2_stats+s2pts_txbytes(a0)
- addq.l #1,ss2_stats+s2pts_txpackets(a0)
- .statsdone:
-
-
- .termio:
- move.l a3,d0 ; have we replied it already?
- beq .next ; we have! process next ioreq
-
- move.l a3,a1
- bsr TermIO ; finish IOrequest
- bra .next ; process next ioreq
-
-
- .copyfromfail:
- ; note: doesn't get called if a3=0
- moveq #S2EVENT_TX|S2EVENT_BUFF,d0
- bsr DoEvent
- clr.l ios2_datalength(a3)
- moveq #S2WERR_BUFF_ERROR,d0
- move.b #S2ERR_NO_RESOURCES,io_error(a3)
- move.l d0,ios2_wireerror(a3)
- bra.s .termio
-
- .xmiterr:
- moveq #S2EVENT_ERROR|S2EVENT_TX,d0
- bsr DoEvent
- bra.s .termio
-
-
-
- ;============================================================
- ; rxintcode(device)
- ; a1
- ;============================================================
- ;
- ; service rx interrupts
- ;
- ; scratch: d0-d1, a0-a1, and a5 (softint must preserve a6!)
- ;
- rxintcode:
- movem.l d6/d7/a6,-(sp)
- move.l exec_base(pc),a6
- move.l a1,a5 ; a5 = device
-
- .nextpage:
-
- MYDISABLE
- delay
- moveq #0,d7
- move.b #DSCM_NODMA|DSCM_PG1|DSCM_START,nic_cr ; select bank 1
- move.b nic_curr,d7 ; d7 = current page
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
- MYENABLE
-
- moveq #0,d6
- delay
- move.b nic_bnry,d6
- addq.w #1,d6 ; d6 = next page (boundary+1)
- cmp.w #RBUFEND/256,d6
- blo.s .nowrap ; end of buffer mem ?
- moveq #RBUF/256,d6 ; wrap around to start
- .nowrap:
- cmp.w d6,d7 ; current page = next page ?
- beq .done ; if so then nothing to get
-
- ifgt 0
- move.w d6,d0
- lea rx_header(pc),a1 ; a1 = buffer
- lsl.w #8,d0 ; d0 = 16 bit page address
- moveq #prhdr_sizeof+ether_data,d1
- bsr RemoteRead ; get packet header
-
- else
-
- ; inlined RemoteRead:
-
- lea nic_data,a0
- lea rx_header(pc),a1 ; a1 = buffer
- delay
- move.b nic_cr,d1 ; save old command
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
- delay
- move.b #prhdr_sizeof+ether_data,nic_rbcr0 ; set count.lo
- delay
- move.b #0,nic_rbcr1 ; set count.hi
- delay
- move.b #0,nic_rsar0 ; set address.lo
- delay
- move.b d6,nic_rsar1 ; set address.hi (d6=16 bit page address hi)
- delay
- move.b #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
-
- ; transfer prhdr_sizeof+ether_data = 4+14 = 18 = 2*9
-
- ifd turboio
- move.l (a0),(a1)+ ; 4*4 = 16
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- move.l (a0),(a1)+
- else
- move.w (a0),(a1)+ ; 4*4 = 16
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- move.w (a0),(a1)+
- endc
- move.w (a0),(a1)+ ; +2
-
- move.b #DSIS_RDC,nic_isr ; Remote DMA Complete
- delay
- move.b d1,nic_cr ; restore old command
-
- endc
-
- move.b rx_header+prhdr_status(pc),d0
- and.b #DSRS_RPC,d0 ; complete packet received ?
- bne.s .goodpacket
-
- bug <"cnet: incomplete packet received",10>
- addq.l #1,dd_devicestats+s2ds_baddata(a5) ; count bad packets received
- bra.s .next
-
- .goodpacket:
- addq.l #1,dd_devicestats+s2ds_packetsreceived(a5) ; count packets received
-
- move.l a5,a0
- move.w d6,d0
- ;lea rx_header(pc),a1
- bsr.s readpacket ; feed packet into waiting ioreqs
-
- .next:
- moveq #0,d0
- move.b rx_header+prhdr_nxtpg(pc),d0 ; get next page number
- move.w d0,d7
- subq.w #1,d0 ; nxtpage-1 = new boundary
- cmp.w #RBUF/256,d0
- bge.s .boundary ; wrap if before 1st page
- moveq #(RBUFEND/256)-1,d0
- .boundary:
- delay
- move.b d0,nic_bnry ; set new boundary
- bra .nextpage ; back for more
-
- .done:
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
- MYDISABLE
- delay
- move.b nic_rsr,d0 ; read rx status
- delay
- move.b nic_cntr0,d0
- delay
- move.b nic_cntr1,d0 ; read counters
- delay
- move.b nic_cntr2,d0
- or.b #DSIM_OVWE|DSIM_RXEE|DSIM_PRXE,dd_imr(a5)
- move.b dd_imr(a5),nic_imr ; allow rx interrupts
- MYENABLE
-
- movem.l (sp)+,d6/d7/a6
- moveq #0,d0
- rts
-
-
-
- ;==============================================================
- ; readpacket( device, [pkthdr], page )
- ; a0 [a1] d0.w
- ;==============================================================
- ;
- ; get packet from network card and feed it to all different
- ; CMD_READ queues. Also call packet filter before doing the copy.
- ;
- ; Note that this is a major improvement to previous implementation,
- ; that only kept one single list of CMD_READs. This finally fixes
- ; sanamon for example.
- ;
- ; Inputs:
- ;
- ; pkthdr = packet header info extracted from nic
- ;
- ; page = 256 byte page in nic RAM that holds packet
- ;
- ;
- readpacket:
- movem.l d2-d7/a2-a6,-(sp)
-
- moveq #0,d6
- move.w d0,d7 ; d7 = page
- move.l a0,a5 ; a5 = device
- move.b rx_header+prhdr_sz1(pc),d6
- moveq #0,d3
- lsl.w #8,d6
- move.w rx_header+prhdr_sizeof+ether_type(pc),d3
- move.b rx_header+prhdr_sz0(pc),d6
- lsl.w #8,d7 ; address=page*256
- sub.w #prhdr_sizeof+ether_data,d6 ; d6 = length of read
- add.w #prhdr_sizeof+ether_data,d7 ; skip pageheader and etherheader
-
- ; dropflag is set to true if at least one protocol stack managed
- ; to get the packet. If this still is zero after the following loop
- ; then I try to feed to for pending S2_READORPHAN request, if any.
-
- moveq #0,d4 ; dropflag
-
- move.l dd_bufmanlist(a5),a3 ; a3 = first bufman
- bra.s .start
-
- ; scan each CMD_READ callers bufmanlist until we find the ioreq
- ; that want this type of packet or till end of list.
-
- .nextreq:
- move.l (a3),d0
- beq.s .nextbufman ; end of this CMD_READ list ?
- cmp.l ios2_packettype(a3),d3
- beq.s .iwantyou ; does it want our packet ?
- cmp.w #1500,d3
- bhi.s .nextnode ; accept 802.3 packets
- cmp.l #1500,ios2_packettype(a3)
- bls.s .iwantyou
- .nextnode:
- move.l d0,a3
- bra.s .nextreq
-
- .iwantyou:
- ; a3 = ioreq
- moveq #1,d2 ; use packetfilter
- bsr .gotreq
- ; note that we only offer it once per caller!
-
- .nextbufman:
- move.l d5,a3 ; a3 = next bufman node in list
- .start:
- move.l (a3),d5
- move.l bufman_rxqueue(a3),a3 ; get pending CMD_READ's list
- bne.s .nextreq ; end of bufman list ?
-
- ; Now we've tried to give the packet to every CMD_READ caller,
- ; and d4 contains the number of iorequests that were succesfully
- ; returned. If d4 is 0 at this point no-one wanted this packet.
-
- tst.l d4
- beq.s .gotdropped ; did oneone want it?
-
- ; Okay, at least one CMD_READ caller got the packet, so we're happy
- ; now and can quit.
-
- .done:
- movem.l (sp)+,d2-d7/a2-a6
- rts
-
-
- .gotdropped:
-
- ; so there were no outstanding CMD_READs or the packet wasn't
- ; accepted by any of them. Okay, check if we have any pending
- ; S2_READORPHAN ioreq in list and if we have return this packet
- ; with it. Note that packet filter must not be used for this
- ; time!
-
- addq.l #1,dd_devicestats+s2ds_unknowntypesreceived(a5)
- move.l dd_orphanlist(a5),a3 ; get first S2_READORPHAN available
- tst.l (a3)
- beq.s .dotrack ; got an orphan ioreq ?
-
- ; d4 = whatever, not important here
- ; a3 = ioreq
- moveq #0,d2 ; indicate S2_READORPHAN call
- bsr.s .gotreq
-
- .dotrack:
-
- ; Update dropped packet statistics, if requested.
-
- move.l dd_tracklist(a5),a0
- .getstat:
- move.l (a0),d0 ; tracking packettypes ?
- beq.s .donetrk
- cmp.l ss2_ptype(a0),d3 ; get tracking entry for this type
- beq.s .dropped
- move.l d0,a0 ; next tracking entry
- bra.s .getstat
-
- .dropped:
- addq.l #1,ss2_stats+s2pts_packetsdropped(a0) ; another packet dropped
- .donetrk:
-
- bug <"cnet: packet type %ld dropped",10>,d3
-
- moveq #S2EVENT_ERROR|S2EVENT_RX,d0
- bsr DoEvent
- bra .done
-
-
-
- .gotreq:
-
- ; Here we have a ioreq in a3 that has requested packets of this type.
- ; 1st we extract the packet from the card unless we have already done
- ; so. d2 = 0 if this ioreq is S2_READORPHAN call (packetfilter must
- ; not be used). if d2 = 1 then this is a regular CMD_READ and
- ; packetfilter must be called.
-
- tst.w d7
- beq.s .gotalready ; have we already read it ?
-
- lea rxbuffer+ether_data(pc),a1
- move.w d7,d0 ; (we only get the user stuff here)
- move.w d6,d1
- ;bsr RemoteRead ; get packet user data from nic
- REMOTEREAD
-
- ifd verbose
- bug <"cnet: rdpkt %08lx%04lx < %08lx%04lx, ">,rxbuffer+ether_dest(pc),rxbuffer+ether_dest+2(pc),rxbuffer+ether_src(pc),rxbuffer+ether_src+2(pc)
- cmp.w #1500,d3
- bhi.s .type
- bug <"(IEEE802.3)len %ld, ">,d3
- bra.s .bytes
- .type:
- bug <"type %ld, ">,d3
- .bytes:
- moveq #ether_data,d0
- add.l d6,d0
- bug <"%ld bytes",10>,d0
- lea rxbuffer+ether_data(pc),a1
- move.l d6,d0
- bsr showpkt
- endc
-
-
- ; Update the packet statistics if required.
-
- move.l dd_tracklist(a5),a0
- .getstats:
- move.l (a0),d0 ; tracking packettypes ?
- beq.s .received
- cmp.l ss2_ptype(a0),d3 ; find stats entry for our type
- beq.s .gotstats
- move.l d0,a0
- bra.s .getstats
- .gotstats:
- add.l d6,ss2_stats+s2pts_rxbytes(a0) ; update stats
- addq.l #1,ss2_stats+s2pts_rxpackets(a0)
- .received:
-
- moveq #0,d7 ; don't try to read it from hw anymore
- .gotalready
-
-
-
- ; next figure out if this ioreq asked the raw or non-raw data,
- ; and skip ether_data bytes from the buffer start if it asked
- ; raw.
-
- move.l d6,ios2_datalength(a3) ; user data size
- lea rxbuffer+ether_data(pc),a6 ; a6=user data
- tst.b io_flags(a3) ; (test SANA2IOB_RAW)
- bpl.s .notraw ; is etherheader wanted ?
- add.w #ether_data+4,ios2_datalength+2(a3) ; raw data size
- lea rxbuffer(pc),a6 ; a6=raw data
- .notraw:
-
- ; now build up the ios2 structure enough so we can call the packet
- ; filter.
-
- lea ios2_dstaddr(a3),a0
- lea rxbuffer+ether_dest(pc),a1 ; or: rx_header+prhdr_sizeof+ether_dest
- move.l (a1)+,(a0)+ ; extract the dst address
- move.w (a1)+,(a0)+
- lea ios2_packettype(a3),a0
- move.l d3,(a0)+ ; packet type
- move.l (a1)+,(a0)+ ; extract the src address
- move.w (a1)+,(a0)+
-
- ; call the packet filter, if available. real men don't use filters. :-)
- ; the truth is out there
-
- tst.l d2
- move.l ios2_buffermanagement(a3),a0
- beq.s .marlboro ; S2_READORPHAN must not use filter!
- move.l bufman_packetfilter(a0),d0
- beq.s .marlboro ; did the caller provide packet filter ?
- move.l d0,a0 ; a0=hook
- move.l a6,a1 ; a1=data
- move.l 8(a0),a4 ; h_entry - get hook assembler entry point
- move.l a3,a2 ; a2=ios2
- jsr (a4)
- tst.l d0
- beq .ignore
- .marlboro: ;-!
-
- ; ok. the packet didn't get filtered, set the BCAST and MCAST
- ; flags according to dstaddr.
-
- btst #0,ios2_dstaddr(a3) ; address = Multicast ?
- beq.s .nmcast
- cmp.l #$ffffffff,ios2_dstaddr(a3)
- bne.s .nbcast ; address = Broadcast ?
- cmp.w #$ffff,ios2_dstaddr+4(a3)
- bne.s .nbcast
- bset #SANA2IOB_BCAST,io_flags(a3) ; set BROADCAST flag in ioreq
- bra.s .nmcast
- .nbcast:
- bset #SANA2IOB_MCAST,io_flags(a3) ; set MULTICAST flag in ioreq
- .nmcast:
-
- ; finally copy the packet data!
-
- move.l ios2_data(a3),a0
- move.l ios2_buffermanagement(a3),a2
- move.l a6,a1
- move.l bufman_copytobuf(a2),a2
- move.l ios2_datalength(a3),d0
- jsr (a2) ; call copytobuf
- tst.l d0
- beq.s .copytobuferr
-
- addq.l #1,d4 ; mark that it wasn't dropped!
-
- ifd verbose
- bug <"cnet: copytobuffed packet ior %08lx %08lx%04lx < %08lx%04lx, type %ld, %ld bytes, ">,a3,ios2_dstaddr(a3),ios2_dstaddr+2(a3),ios2_srcaddr(a3),ios2_srcaddr+2(a3),ios2_packettype(a3),ios2_datalength(a3)
- tst.b io_flags(a3)
- bpl.s .v1
- bug <"RAW ">
- .v1:
- btst #SANA2IOB_BCAST,io_flags(a3)
- beq.s .v2
- bug <"BCAST ">
- .v2:
- btst #SANA2IOB_MCAST,io_flags(a3)
- beq.s .v3
- bug <"MCAST ">
- .v3:
- bug <10>
- endc
-
- .termit:
- move.l a3,a1
- REMOVE ; pull it off the list
- move.l a3,a1
- bra TermIO ; IO finished
-
-
- .ignore:
- bug <"cnet: packet type %ld for %08lx ior filtered",10>,d3,a3
-
- ; the packet got rejected by packet filter!
- rts
-
-
- .copytobuferr:
- ; oh fuck.. copytobuf failed!
- bug <10,"cnet: copytobuf failed!",10>
-
- moveq #S2EVENT_RX|S2EVENT_BUFF,d0
- bsr DoEvent
- clr.l ios2_datalength(a3)
- moveq #S2WERR_BUFF_ERROR,d0
- move.b #S2ERR_NO_RESOURCES,io_error(a3)
- move.l d0,ios2_wireerror(a3)
- bra.s .termit
-
-
-
-
- ;======================================================================
- ; init_card(device)
- ; a1
- ;======================================================================
- ;
- ; Initialise PCMCIA card
- ;
- init_card:
- bug <"cnet: init_card",10>
-
- movem.l d3-d6/a3/a6,-(sp)
- move.l a1,a3 ; a3 = device
- btst #DDB_OWNED,dd_flags(a3) ; do we own the card already?
- bne .owned
-
- move.l dd_cardres(a3),d0
- bne.s .gotres
- move.l exec_base(pc),a6
- lea cardname(pc),a1
- jsr _LVOOpenResource(a6) ; open credit card resource
- move.l d0,dd_cardres(a3)
- beq .error
- .gotres:
-
- lea dd_cardhandle(a3),a1
-
- lea dd_cardremoved(a3),a0 ; init interrupt for card removed
- move.l a3,is_data(a0)
- move.l #card_removed_code,is_code(a0)
- move.l a0,cah_CardRemoved(a1)
-
- lea dd_cardinserted(a3),a0 ; init interrupt for card inserted
- move.l a3,is_data(a0)
- move.l #card_inserted_code,is_code(a0)
- move.l a0,cah_CardInserted(a1)
-
- lea dd_cardstatus(a3),a0 ; init interrupt for status change
- move.l a3,is_data(a0)
-
- move.l dd_cardres(a3),a6
- cmp.w #39,LIB_VERSION(a6) ; got CARDB_POSTSTATUS (v39+) ?
- blo.s .oldie
-
- move.l #status_int_code_v39,is_code(a0)
- move.b #CARDF_IFAVAILABLE|CARDF_POSTSTATUS,cah_cardflags(a1)
- bra.s .was_goldie
-
- .oldie:
- move.l #status_int_code_v37,is_code(a0)
- move.b #CARDF_IFAVAILABLE,cah_cardflags(a1)
- .was_goldie:
- move.l a0,cah_CardStatus(a1)
-
- lea devicename(pc),a0
- move.l a0,ln_name(a1)
- move.b #20,ln_pri(a1) ; high priority for I/O card
-
- jsr _LVOOwnCard(a6) ; own card (sets up interrupt vectors)
- tst.l d0
- bne .error
-
- or.b #DDF_CARDIN|DDF_OWNED,dd_flags(a3) ; card is inserted & owned by us
-
- .owned:
- lea dd_cardhandle(a3),a1
- lea tuple(pc),a0
- moveq #CISTPL_FUNC_ID,d1
- moveq #40,d0
- move.l dd_cardres(a3),a6
- jsr _LVOCopyTuple(a6) ; read function tuple
- tst.l d0
- beq .error
-
- lea tuple(pc),a0
- move.b 2(a0),d0
- cmp.b #CISTPL_FUNCID_NETWORK,d0 ; must be a network card!
- bne .error
-
- lea dd_cardhandle(a3),a1
- lea tuple(pc),a0
- moveq #CISTPL_CONF_MAP,d1
- moveq #40,d0
- move.l dd_cardres(a3),a6
- jsr _LVOCopyTuple(a6) ; read config map tuple
- tst.l d0
- beq .error
-
- lea tuple(pc),a0
- move.b 2(a0),d0
- and.w #$03,d0 ; (number of address bytes)-1
- moveq #0,d5
-
- .getaddr:
- lsl.l #8,d5
- move.b 4(a0,d0.w),d5 ; extract config register address
- subq.w #1,d0
- bpl.s .getaddr
-
- and.l #$0001FFFF,d5 ; limit to attribute memory range
- lea dd_cardhandle(a3),a1
- moveq #CISTPL_CONFIG,d1
- moveq #40,d0
- jsr _LVOCopyTuple(a6) ; read 1st config tuple
- tst.l d0
- beq.s .error
-
- lea dd_cardhandle(a3),a1
- move.l #CARDF_DISABLE_WP|CARDF_ENABLE_DIGAUDIO,d1
- jsr _LVOCardMiscControl(a6) ; enable card I/O functions
- lea tuple(pc),a0
- move.b 2(a0),d0 ; extract configuration ID value
-
- .setconfig:
- and.b #$3f,d0
- lea AttrMem,a0
- add.l d5,a0
- move.b d0,(a0) ; put ID into card config register
-
- .ok:
- bug <"cnet: init_card: OK",10>
- moveq #0,d0 ; card is active, return OK
-
- .done:
- movem.l (sp)+,d3-d6/a3/a6
- rts
-
- .error:
- bug <"cnet: init_card: failed!",10>
- moveq #S2EVENT_ERROR|S2EVENT_HARDWARE,d0
- bsr DoEvent
- moveq #-1,d0 ; card not available, return error
- bra.s .done
-
-
-
- ;=================================================================
- ; initialise device data structures
- ;=================================================================
- ;
- ; init_device(device)
- ; a1
- ;
- init_device:
-
- movem.l a3/a6,-(sp)
- move.l a1,a3
- bset #DDB_DEVINIT,dd_flags(a3) ; already initialised ?
- bne .done
-
- move.l exec_base(pc),a6
-
- lea dd_orphanlist(a3),a0 ; New MinList for orphan queue
- NEWLIST a0
- lea dd_writelist(a3),a0 ; New MinList for write queue
- NEWLIST a0
- lea dd_eventlist(a3),a0 ; New MinList for event queue
- NEWLIST a0
- lea dd_bufmanlist(a3),a0 ; New MinList for bufman vectors
- NEWLIST a0
- lea dd_tracklist(a3),a0 ; New MinList for tracking
- NEWLIST a0
- lea dd_multicasts(a3),a0 ; New MinList for multicast filters
- NEWLIST a0
-
- lea dd_multicastssema(a3),a0
- jsr _LVOInitSemaphore(a6)
-
- lea dd_rxint+ln_type(a3),a1
- lea rxintname(pc),a0
- move.w #(NT_INTERRUPT<<8)|16,(a1)+ ; priority 16
- move.l a0,(a1)+ ; set up rx swi
- lea rxintcode(pc),a0
- move.l a3,(a1)+
- move.l a0,(a1)+
-
- lea dd_txint+ln_type(a3),a1
- lea txintname(pc),a0
- move.w #(NT_INTERRUPT<<8)|0,(a1)+ ; priority 0
- move.l a0,(a1)+ ; set up tx swi
- lea txintcode(pc),a0
- move.l a3,(a1)+
- move.l a0,(a1)+
-
- .done:
- movem.l (sp)+,a3/a6
- rts
-
-
-
- ;============================================================
- ; PCMCIA status change interrupt
- ;============================================================
- ;
- ; Occurs whenever a PCMCIA status line changes
- ;
- ; eg. when the network card activates it's interrupt line
- ;
- ;
- ; entry: d0 = status change(s)
- ; a1 = device
- ;
- ; exit: d0 must be preserved!
- ;
-
- STATINT MACRO
-
- movem.l d2-d6/a2-a4,-(sp)
- move.l a1,a4 ; a4 = device
- btst #DDB_NICUP,dd_flags(a4) ; is nic working ?
- beq .done
-
- move.l d0,d6 ; d6 = status changes
- move.l exec_base(pc),a6
-
- move.b nic_cr,d5 ; save old command
- delay
- move.b #0,nic_imr ; prevent nic interrupts
- bra .checkint
-
- ; interrupt service loop (d3 = interrupt status)
-
- .intloop:
- btst #DSIB_ROVRN,d3 ; Overwrite warning enable ?
- beq .no_overflow
- ; receiver ring buffer overflowed (eek!)
- addq.l #1,dd_overflows(a4)
- delay
- move.b #0,nic_rbcr0
- delay
- move.b #0,nic_rbcr1 ; reset remote byte count
- delay
- move.b #DSTC_LB0,nic_tcr
- delay ; monitor mode
- move.b #DSRC_MON,nic_rcr
- delay
- move.b #DSCM_NODMA|DSCM_START,nic_cr ; try to restart controller
- delay
- move.b #DSRC_AB,nic_rcr
- delay ; normal rx mode
- move.b #0,nic_tcr
- .no_overflow:
-
- btst #DSIB_RXE,d3 ; Receive error enable ?
- beq.s .norxerr
- ; bug <"cnet: rx error",10>
- addq.l #1,dd_devicestats+s2ds_baddata(a4) ; another bad rx packet ?
- delay
- move.b nic_rsr,d0 ; read rx status
- delay
- move.b nic_cntr0,d0
- delay
- move.b nic_cntr1,d0 ; read counters
- delay
- move.b nic_cntr2,d0
- bra.s .rx
- .norxerr:
-
- btst #DSIB_RX,d3 ; Packet received enable ?
- beq.s .no_rx
-
- ; new packet(s) arrived in receive ring buffer
- .rx:
- and.b #~(DSIM_OVWE|DSIM_RXEE|DSIM_PRXE),dd_imr(a4) ; ignore rx ints
- lea dd_rxint(a4),a1
- jsr _LVOCause(a6) ; to copy packet(s) into waiting ioreq(s)
- .no_rx:
-
- btst #DSIB_TXE,d3 ; Transmit error enable ?
- bne.s .tx
- btst #DSIB_TX,d3 ; Packet transmitted enable ?
- beq .no_tx
-
- .tx:
- ; a packet has just been transmitted
- moveq #0,d0
- delay
- move.b nic_ncr,d0 ; read collision count
- bclr #DDB_TX,dd_flags(a4) ; buffer now free
- add.l d0,dd_retries(a4) ; increment retry count
- addq.l #1,dd_devicestats+s2ds_packetssent(a4) ; count packets sent
- lea dd_txint(a4),a1
- jsr _LVOCause(a6) ; to transmit next packet
- .no_tx:
-
- btst #DSIB_CTRS,d3 ; counter overflow ?
- beq.s .nocounter
-
- ; counter overflow
- delay
- move.b nic_cntr0,d0
- delay
- move.b nic_cntr1,d0 ; read counters
- delay
- move.b nic_cntr2,d0
- .nocounter:
-
-
- .checkint:
- delay
- move.b nic_isr,d3 ; d3 = nic interrupt status
- delay
- move.b d3,nic_isr ; clear current interrupt bit(s)
- and.b dd_imr(a4),d3
- bne .intloop ; any valid interrupts ?
-
- delay
- move.b d5,nic_cr ; restore old command
-
- ENDM
-
-
-
- CNOP 0,4
- status_int_code_v37:
-
- STATINT
-
- eor.b #$2c,d6
- or.b #$c0,d6
- move.b d6,$da9000 ; clear PCMCIA status change bits
- delay
- move.b dd_imr(a4),nic_imr ; enable nic interrupts
- moveq #0,d0 ; don't clear status bits coz we did
-
- .done:
- movem.l (sp)+,d2-d6/a2-a4
- rts
-
-
- CNOP 0,4
- status_int_code_v39:
-
- STATINT
-
- delay
- move.b dd_imr(a4),nic_imr ; enable nic interrupts
- move.l d6,d0 ; return original d0
-
- .done:
- movem.l (sp)+,d2-d6/a2-a4
- rts
-
-
-
- ;============================================================
- ; PCMCIA Card Inserted interrupt
- ;============================================================
- ;
- ; Occurs whenever a PCMCIA card is plugged in
- ;
- ; NOTE: card.resource has given us ownership of the card
- ;
- ; entry: a1 = device
- ;
- ; exit: d0,d1,a0,a1,a5,a6 = scratch
- ;
- card_inserted_code:
- bug <"cnet: PCMCIA card inserted",10>
-
- move.l a1,a5
-
- tst.w lib_opencnt(a5) ; is someone interested about cards ?
- beq.s .done
-
- or.b #DDF_CARDIN|DDF_OWNED,dd_flags(a5) ; card is inserted & we own the card again
-
- bsr init_card
- tst.l d0 ; attempt to init pcmcia card
- bne.s .releasecard
-
- move.l a5,a1
- bsr init_nic ; attempt to start controller
- tst.l d0
- beq.s .good
-
- .releasecard:
- lea dd_cardhandle(a5),a1
- move.l dd_cardres(a5),a6
- moveq #0,d0
- jsr _LVOReleaseCard(a6) ; release foreign or bad card
- bclr #DDB_OWNED,dd_flags(a5)
- bra.s .done
-
- .good:
- btst #DDB_OFFLINE,dd_flags(a5) ; has device been put offline ?
- bne.s .done
- bset #DDB_ONLINE,dd_flags(a5) ; device is now online
- moveq #S2EVENT_ONLINE,d0
- bra DoEvent ; return ONLINE event
-
- .done:
- rts
-
-
-
- ;============================================================
- ; PCMCIA Card Removed interrupt
- ;============================================================
- ;
- ; Occurs whenever a PCMCIA card is unplugged
- ;
- ; entry: a1 = device
- ;
- ; exit: d0,d1,a0,a1,a5,a6 = scratch
- ;
- card_removed_code:
- bug <"cnet: PCMCIA card removed",10>
-
- move.l a1,a5 ; a5 = device
- ;and.b #~(DDF_OWNED|DDF_CARDIN|DDF_ONLINE|DDF_NICUP|DDF_CONFIGURED),dd_flags(a5)
- and.b #~(DDF_OWNED|DDF_CARDIN|DDF_ONLINE|DDF_NICUP),dd_flags(a5)
- lea dd_cardhandle(a5),a1
- move.l dd_cardres(a5),a6
- moveq #0,d0
- jsr _LVOReleaseCard(a6) ; release card
-
- moveq #S2EVENT_OFFLINE,d0
- bra DoEvent ; return OFFLINE event
-
-
-
- ; debugging stuff...
-
- ifd verbose
- showpkt:
- movem.l a0-a1/d0-d2,-(sp)
- bug <10>
- moveq #0,d1
-
- .rows:
- moveq #15,d2
- lea .string(pc),a0
-
- .bytes:
- move.b (a1)+,d1
- cmp.b #' ',d1
- blo.s .dot
- cmp.b #'z',d1
- bhs.s .dot
- move.b d1,(a0)+
- bra.s .ends
- .dot:
- move.b #'.',(a0)+
- .ends:
- move.b #0,(a0)
- bug <"%02lx ">,d1
- subq.w #1,d0
- beq.s .end
- dbf d2,.bytes
- bra.s .shows
-
- .endspc:
- bug <" ">
- .end:
- dbf d2,.endspc
-
- .shows:
- bug <" %s",10>,#.string
- tst.w d0
- bne.s .rows
-
- bug <10,10>
- movem.l (sp)+,a0-a1/d0-d2
- rts
-
- .string:
- ds.b 16
- dc.b 0
- even
- endc
-
-
- rxintname:
- dc.b "cnet rx softint",0
- txintname:
- dc.b "cnet tx softint",0
-
- cardname:
- dc.b "card.resource",0
- timerdevname:
- dc.b "timer.device",0
- utilityName:
- dc.b "utility.library",0
-
- multiname:
- dc.b "bad multicasts",0
- retryname:
- dc.b "retries",0
-
- DeviceName:
- dc.b "cnet.device",0
-
-
- dc.b "$VER: "
- IDString:
- dc.b "cnet.device "
- VERSTR
- ifeq __CPU-68000
- dc.b " 68000+"
- else
- ifge __CPU-68020
- dc.b " 68020+"
- endc
- endc
- ifd turboio
- dc.b "/turboio"
- endc
- ifd debug
- dc.b "/debug"
- endc
- dc.b " by Harry ",34,"Piru",34," Sintonen",10,0
-
-
- ; devicequery block
-
- CNOP 0,2
- size_supplied:
- dc.l S2DQ_SIZE ; bytes supplied (size of this block)
- dc.l 0 ; this is type 0
- dc.l 0 ; this document is level 0
- dc.w ETHER_ADDR_SIZE*8 ; address size in bits
- dc.l ETHERPKT_SIZE ; maximum packet data size
- dc.l 10000000 ; line rate (10 Megabits/sec)
- dc.l S2WIRETYPE_ETHERNET ; what the wire is
-
-
- ; default station address to use if the card won't give it to us.
-
- CNOP 0,2
- default_address:
- dc.b $00,$00,$12,$34,$56,$78 ; replace this with your card's address!
-
-
- ;--------------------------------------------------------
- ; Global data
- ;--------------------------------------------------------
-
- CNOP 0,4
-
- exec_base: dc.l 0 ; local copy of execbase
-
- utility_base: dc.l 0 ; for walking taglist
-
- me_myself: dc.l 0 ; pointer to this device
-
- timerdevice: dc.l 0 ; timer device base
-
- mcastaddr: ds.b 8 ; multicast address filter bitfield
-
-
- ; ---- Timer I/O Request ----
- CNOP 0,2
- timereq:
- dc.l 0 ; ln_head } }
- dc.l 0 ; ln_pred } }
- dc.b 0 ; ln_type } mp_node }
- dc.b 0 ; ln_pri } } io_message
- dc.l 0 ; ln_name } }
- dc.l 0 ; mn_replyport }
- dc.w 0 ; mn_length }
- dc.l 0 ; io_device
- dc.l 0 ; io_unit
- dc.w 0 ; io_command
- dc.b 0 ; io_flags
- dc.b 0 ; io_error
- dc.l 0 ; tv_secs
- dc.l 0 ; tv_micros
-
-
- tuple: ds.b 48 ; PCMCIA tuple buffer
-
-
- ; linked with phxlnk so no need for separate bss hunk!
- ; section buffers,bss
-
- CNOP 0,8
- rx_header:
- ds.b prhdr_sizeof
- rxbuffer:
- ds.b PKTBUF_SIZE-prhdr_sizeof ; received packet buffer
-
- CNOP 0,8
- txbuffer:
- ds.b PKTBUF_SIZE ; transmit packet buffer
-
-
- CNOP 0,2
- Endcode:
-